pciIomapLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:22k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pciIomapLib.c - Support for PCI drivers */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01i,27oct01,dat  Adding warnings about obsolete drivers
  8. 01h,15oct98,dat  SPR 9098, added iv.h and private/semLibP.h
  9. 01g,12jan97,hdn  changed variable name "vender" to "vendor".
  10. 01f,12jan97,hdn  changed variable name "class" to "classCodeReg".
  11. 01e,03dec96,hdn  added single/multi function check.
  12. 01d,16sep96,dat  made pciConfigMech global (for pciIomapShow).
  13. 01c,06aug96,hdn  added pciInt(), pciIntConnect() and pciIntDisconnect().
  14. 01b,14mar96,hdn  re-written.  changed parameters of the functions.
  15.  removed BIOS dependent codes.
  16. 01a,25feb95,bcs  written
  17. */
  18. /*
  19. DESCRIPTION
  20. This library is PCI Revision 2.1 compliant.
  21. This module contains routines to support PCI bus mapped on IO address space
  22. for x86 and PowerPC architecture.  Functions in this library should not be
  23. called from the interrupt level, except pciInt(), since it uses a mutual
  24. exclusion semaphore for consecutive register access.  
  25. The functions addressed here include:
  26.   - Initialize the library.
  27.   - Locate the device by deviceID and vendorID.
  28.   - Locate the device by classCode.
  29.   - Generate the special cycle.
  30.   - Access its configuration registers.
  31.   - Connect a shared interrupt handler.
  32.   - Disconnect a shared interrupt handler.
  33.   - Master shared interrupt handler.
  34. There are functions to access the IO address space.  In x86 architecture,
  35. they are sysInXXX() and sysOutXXX().  Macro PCI_IN_XXX() and PCI_OUT_XXX()
  36. are provided to use other IO address space functions.
  37. Shared PCI interrupt are supported by three functions: pciInt(),
  38. pciIntConnect(), pciIntDisconnect().  pciIntConnect() adds the specified
  39. interrupt handler to the link list and pciIntDisconnect() removes it from
  40. the link list.  Master interrupt handler pciInt() executes these interrupt
  41. handlers in the link list for a PCI interrupt.  Each interrupt handler must
  42. check the device dependent interrupt status bit to determine the source of
  43. the interrupt, since it simply execute all interrupt handlers in the link
  44. list.  pciInt() should be attached by intConnect() function in the BSP 
  45. initialization with its parameter. The parameter is an IRQ associated 
  46. to the PCI interrupt.
  47. */
  48. #include "vxWorks.h"
  49. #include "stdio.h"
  50. #include "stdlib.h"
  51. #include "string.h"
  52. #include "intLib.h"
  53. #include "sysLib.h"
  54. #include "drv/pci/pciIomapLib.h"
  55. #include "iv.h"
  56. #include "private/semLibP.h"
  57. /* pciIomapLib is being obsoleted. Please use pciConfigLib instead. */
  58. #warning "src/drv/pci/pciIomapLib.c is outdated. Please use pciConfigLib"
  59. /* defines */
  60. #ifndef PCI_IN_BYTE
  61. #define PCI_IN_BYTE(x) sysInByte (x)
  62. #endif
  63. #ifndef PCI_IN_WORD
  64. #define PCI_IN_WORD(x) sysInWord (x)
  65. #endif
  66. #ifndef PCI_IN_LONG
  67. #define PCI_IN_LONG(x) sysInLong (x)
  68. #endif
  69. #ifndef PCI_OUT_BYTE
  70. #define PCI_OUT_BYTE(x,y) sysOutByte (x,y)
  71. #endif
  72. #ifndef PCI_OUT_WORD
  73. #define PCI_OUT_WORD(x,y) sysOutWord (x,y)
  74. #endif
  75. #ifndef PCI_OUT_LONG
  76. #define PCI_OUT_LONG(x,y) sysOutLong (x,y)
  77. #endif
  78. /* globals */
  79. STATUS pciLibInitStatus = NONE; /* initialization done */
  80. DL_LIST pciIntList[PCI_IRQ_LINES]; /* link list of int handlers */
  81. int pciConfigMech = NONE; /* 1=mechanism-1, 2=mechanism-2 */
  82. /* locals */
  83. LOCAL int pciConfigAddr0; /* config-addr-reg, CSE-reg*/
  84. LOCAL int pciConfigAddr1; /* config-data-reg, forward-reg */
  85. LOCAL int pciConfigAddr2; /* not-used, base-addr */
  86. LOCAL SEMAPHORE pciMuteSem; /* mutual exclusion semaphore */
  87. /*******************************************************************************
  88. *
  89. * pciIomapLibInit - initialize the configuration access-method and addresses
  90. *
  91. * This routine initializes the configuration access-method and addresses.
  92. *
  93. * Configuration mechanism one utilizes two 32-bit IO ports located at addresses
  94. * 0x0cf8 and 0x0cfc. These two ports are:
  95. *   - 32-bit configuration address port, at 0x0cf8
  96. *   - 32-bit configuration data port, at 0x0cfc
  97. * Accessing a PCI function's configuration port is two step process.
  98. *   - Write the bus number, physical device number, function number and 
  99. *     register number to the configuration address port.
  100. *   - Perform an IO read from or an write to the configuration data port.
  101. *
  102. * Configuration mechanism two uses following two single-byte IO ports.
  103. *   - Configuration space enable, or CSE, register, at 0x0cf8
  104. *   - Forward register, at 0x0cfa
  105. * To generate a PCI configuration transaction, the following actions are
  106. * performed.
  107. *   - Write the target bus number into the forward register.
  108. *   - Write a one byte value to the CSE register at 0x0cf8.  The bit
  109. *     pattern written to this register has three effects: disables the
  110. *     generation of special cycles; enables the generation of configuration
  111. *     transactions; specifies the target PCI functional device.
  112. *   - Perform a one, two or four byte IO read or write transaction within
  113. *     the IO range 0xc000 through 0xcfff.
  114. *
  115. * RETURNS:
  116. * OK, or ERROR if a mechanism is not 1 or 2.
  117. *
  118. */
  119. STATUS pciIomapLibInit
  120.     (
  121.     int mechanism, /* configuration mechanism: 1 or 2 */
  122.     int addr0, /* config-addr-reg / CSE-reg */
  123.     int addr1, /* config-data-reg / Forward-reg */
  124.     int addr2 /* none            / Base-address */
  125.     )
  126.     {
  127.     int ix;
  128.     if (pciLibInitStatus != NONE)
  129. return (pciLibInitStatus);
  130.     switch (mechanism)
  131. {
  132. case PCI_MECHANISM_1:
  133. case PCI_MECHANISM_2:
  134.     pciConfigMech = mechanism;
  135.     pciConfigAddr0 = addr0;
  136.     pciConfigAddr1 = addr1;
  137.     pciConfigAddr2 = addr2;
  138.     pciLibInitStatus = OK;
  139.     break;
  140. default:
  141.          pciLibInitStatus = ERROR;
  142.     break;
  143. }
  144.     semMInit (&pciMuteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE | 
  145.       SEM_INVERSION_SAFE);
  146.     for (ix = 0; ix < PCI_IRQ_LINES; ix++)
  147.         dllInit (&pciIntList[ix]);
  148.     return (pciLibInitStatus);
  149.     }
  150. /*******************************************************************************
  151. *
  152. * pciFindDevice - find the nth device with the given device & vendor ID
  153. *
  154. * This routine finds the nth device with the given device & vendor ID.
  155. *
  156. * RETURNS:
  157. * OK, or ERROR if the deviceId and vendorId didn't match.
  158. *
  159. */
  160. STATUS pciFindDevice
  161.     (
  162.     int vendorId, /* vendor ID */
  163.     int deviceId, /* device ID */
  164.     int index, /* desired instance of device */
  165.     int * pBusNo, /* bus number */
  166.     int * pDeviceNo, /* device number */
  167.     int * pFuncNo /* function number */
  168.     )
  169.     {
  170.     STATUS status = ERROR;
  171.     int busNo;
  172.     int deviceNo;
  173.     int funcNo;
  174.     short device;
  175.     short vendor;
  176.     char header;
  177.     if (pciLibInitStatus != OK) /* sanity check */
  178.         return (ERROR);
  179.     for (busNo=0; busNo < 0xff; busNo++)
  180.         for (deviceNo=0; deviceNo < 0x1f; deviceNo++)
  181.             for (funcNo=0; funcNo < 0x07; funcNo++)
  182. {
  183. /* avoid a special bus cycle */
  184. if ((deviceNo == 0x1f) && (funcNo == 0x07))
  185.     continue;
  186. pciConfigInWord (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID,
  187.  &vendor);
  188. pciConfigInWord (busNo, deviceNo, funcNo, PCI_CFG_DEVICE_ID,
  189.  &device);
  190. if ((vendor == (short)vendorId) && 
  191.     (device == (short)deviceId) &&
  192.     (index-- == 0))
  193.     {
  194.     *pBusNo = busNo;
  195.     *pDeviceNo = deviceNo;
  196.     *pFuncNo = funcNo;
  197.     status = OK;
  198.     break; /* terminate loop */
  199.     }
  200. /* goto next device if it is a single function device */
  201. pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE, 
  202.  &header);
  203. if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
  204.     break;
  205. }
  206.     return (status);
  207.     }
  208. /*******************************************************************************
  209. *
  210. * pciFindClass - find the nth device with the given class(3 bytes).
  211. *
  212. * This routine finds the nth device with the given class(class subclass prog).
  213. *
  214. * RETURNS:
  215. * OK, or ERROR if the class didn't match.
  216. *
  217. */
  218. STATUS pciFindClass
  219.     (
  220.     int classCode, /* class code */
  221.     int index, /* desired instance of device */
  222.     int * pBusNo, /* bus number */
  223.     int * pDeviceNo, /* device number */
  224.     int * pFuncNo /* function number */
  225.     )
  226.     {
  227.     STATUS status = ERROR;
  228.     int busNo;
  229.     int deviceNo;
  230.     int funcNo;
  231.     int classCodeReg;
  232.     char header;
  233.     if (pciLibInitStatus != OK) /* sanity check */
  234.         return (ERROR);
  235.     for (busNo=0; busNo < 0xff; busNo++)
  236.         for (deviceNo=0; deviceNo < 0x1f; deviceNo++)
  237.             for (funcNo=0; funcNo < 0x07; funcNo++)
  238. {
  239. /* avoid a special bus cycle */
  240. if ((deviceNo == 0x1f) && (funcNo == 0x07))
  241.     continue;
  242. pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_REVISION,
  243.  &classCodeReg);
  244. if ((((classCodeReg >> 8) & 0x00ffffff) == classCode) &&
  245.     (index-- == 0))
  246.     {
  247.     *pBusNo = busNo;
  248.     *pDeviceNo = deviceNo;
  249.     *pFuncNo = funcNo;
  250.     status = OK;
  251.     break; /* terminate loop */
  252.     }
  253. /* goto next device if it is a single function device */
  254. pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE, 
  255.  &header);
  256. if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
  257.     break;
  258. }
  259.     return (status);
  260.     }
  261. /*******************************************************************************
  262. *
  263. * pciPack - pack parameters for the Configuration Address Register
  264. *
  265. * This routine packs three parameters into one integer for accessing the
  266. * Configuration Address Register
  267. *
  268. * RETURNS:
  269. * packed integer.
  270. *
  271. */
  272. LOCAL int pciPack
  273.     (
  274.     int busNo, /* bus number */
  275.     int deviceNo, /* device number */
  276.     int funcNo /* function number */
  277.     )
  278.     {
  279.     return (((busNo    << 16) & 0x00ff0000) |
  280.     ((deviceNo << 11) & 0x0000f800) |
  281.     ((funcNo   << 8)  & 0x00000700));
  282.     }
  283. /*******************************************************************************
  284. *
  285. * pciConfigInByte - read one byte from the PCI configuration space
  286. *
  287. * This routine reads one byte from the PCI configuration space
  288. *
  289. * RETURNS:
  290. * OK, or ERROR if this library is not initialized.
  291. *
  292. */
  293. STATUS pciConfigInByte
  294.     (
  295.     int busNo, /* bus number */
  296.     int deviceNo, /* device number */
  297.     int funcNo, /* function number */
  298.     int address, /* address of the configuration space */
  299.     char * pData /* data read from the address */
  300.     )
  301.     {
  302.     int retval = 0;
  303.     if (pciLibInitStatus != OK) /* sanity check */
  304.         return (ERROR);
  305.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  306.     switch (pciConfigMech)
  307. {
  308. case PCI_MECHANISM_1:
  309.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  310.           (address & 0xfc) | 0x80000000);
  311.     retval = PCI_IN_BYTE (pciConfigAddr1 + (address & 0x3));
  312.     break;
  313. case PCI_MECHANISM_2:
  314.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  315.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  316.     retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  317.   (address & 0xfc));
  318.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  319.     retval >>= (address & 0x03) * 8;
  320.     break;
  321. default:
  322.     break;
  323. }
  324.     semGive (&pciMuteSem); /* mutual execlusion stop */
  325.     *pData = retval;
  326.     return (OK);
  327.     }
  328. /*******************************************************************************
  329. *
  330. * pciConfigInWord - read one word from the PCI configuration space
  331. *
  332. * This routine reads one word from the PCI configuration space
  333. *
  334. * RETURNS:
  335. * OK, or ERROR if this library is not initialized.
  336. *
  337. */
  338. STATUS pciConfigInWord
  339.     (
  340.     int busNo, /* bus number */
  341.     int deviceNo, /* device number */
  342.     int funcNo, /* function number */
  343.     int address, /* address of the configuration space */
  344.     short * pData /* data read from the address */
  345.     )
  346.     {
  347.     int retval = 0;
  348.     if (pciLibInitStatus != OK) /* sanity check */
  349.         return (ERROR);
  350.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  351.     switch (pciConfigMech)
  352. {
  353. case PCI_MECHANISM_1:
  354.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  355.           (address & 0xfc) | 0x80000000);
  356.     retval = PCI_IN_WORD (pciConfigAddr1 + (address & 0x2));
  357.     break;
  358. case PCI_MECHANISM_2:
  359.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  360.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  361.     retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  362.   (address & 0xfc));
  363.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  364.     retval >>= (address & 0x02) * 8;
  365.     break;
  366. default:
  367.     break;
  368. }
  369.     semGive (&pciMuteSem); /* mutual execlusion stop */
  370.     *pData = retval;
  371.     return (OK);
  372.     }
  373. /*******************************************************************************
  374. *
  375. * pciConfigInLong - read one longword from the PCI configuration space
  376. *
  377. * This routine reads one longword from the PCI configuration space
  378. *
  379. * RETURNS:
  380. * OK, or ERROR if this library is not initialized.
  381. *
  382. */
  383. STATUS pciConfigInLong
  384.     (
  385.     int busNo, /* bus number */
  386.     int deviceNo, /* device number */
  387.     int funcNo, /* function number */
  388.     int address, /* address of the configuration space */
  389.     int * pData /* data read from the address */
  390.     )
  391.     {
  392.     int retval = 0;
  393.     if (pciLibInitStatus != OK) /* sanity check */
  394.         return (ERROR);
  395.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  396.     switch (pciConfigMech)
  397. {
  398. case PCI_MECHANISM_1:
  399.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  400.           (address & 0xfc) | 0x80000000);
  401.     retval = PCI_IN_LONG (pciConfigAddr1);
  402.     break;
  403. case PCI_MECHANISM_2:
  404.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  405.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  406.     retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  407.   (address & 0xfc));
  408.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  409.     break;
  410. default:
  411.     break;
  412. }
  413.     semGive (&pciMuteSem); /* mutual execlusion stop */
  414.     *pData = retval;
  415.     return (OK);
  416.     }
  417. /*******************************************************************************
  418. *
  419. * pciConfigOutByte - write one byte to the PCI configuration space
  420. *
  421. * This routine writes one byte to the PCI configuration space.
  422. *
  423. * RETURNS:
  424. * OK, or ERROR if this library is not initialized.
  425. *
  426. */
  427. STATUS pciConfigOutByte
  428.     (
  429.     int busNo, /* bus number */
  430.     int deviceNo, /* device number */
  431.     int funcNo, /* function number */
  432.     int address, /* address of the configuration space */
  433.     char data /* data written to the address */
  434.     )
  435.     {
  436.     int retval;
  437.     int mask = 0x000000ff;
  438.     if (pciLibInitStatus != OK) /* sanity check */
  439.         return (ERROR);
  440.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  441.     switch (pciConfigMech)
  442. {
  443. case PCI_MECHANISM_1:
  444.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  445.           (address & 0xfc) | 0x80000000);
  446.     PCI_OUT_BYTE ((pciConfigAddr1 + (address & 0x3)), data);
  447.     break;
  448. case PCI_MECHANISM_2:
  449.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  450.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  451.     retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  452.   (address & 0xfc));
  453.     data = (data & mask) << ((address & 0x03) * 8);
  454.     mask <<= (address & 0x03) * 8;
  455.     retval = (retval & ~mask) | data;
  456.     PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  457.   (address & 0xfc)), retval);
  458.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  459.     break;
  460. default:
  461.     break;
  462. }
  463.     semGive (&pciMuteSem); /* mutual execlusion stop */
  464.     return (OK);
  465.     }
  466. /*******************************************************************************
  467. *
  468. * pciConfigOutWord - write one word to the PCI configuration space
  469. *
  470. * This routine writes one word to the PCI configuration space.
  471. *
  472. * RETURNS:
  473. * OK, or ERROR if this library is not initialized.
  474. *
  475. */
  476. STATUS pciConfigOutWord
  477.     (
  478.     int busNo, /* bus number */
  479.     int deviceNo, /* device number */
  480.     int funcNo, /* function number */
  481.     int address, /* address of the configuration space */
  482.     short data /* data written to the address */
  483.     )
  484.     {
  485.     int retval;
  486.     int mask = 0x0000ffff;
  487.     if (pciLibInitStatus != OK) /* sanity check */
  488.         return (ERROR);
  489.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  490.     switch (pciConfigMech)
  491. {
  492. case PCI_MECHANISM_1:
  493.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  494.           (address & 0xfc) | 0x80000000);
  495.     PCI_OUT_WORD ((pciConfigAddr1 + (address & 0x2)), data);
  496.     break;
  497. case PCI_MECHANISM_2:
  498.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  499.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  500.     retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  501.   (address & 0xfc));
  502.     data = (data & mask) << ((address & 0x02) * 8);
  503.     mask <<= (address & 0x02) * 8;
  504.     retval = (retval & ~mask) | data;
  505.     PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  506.   (address & 0xfc)), retval);
  507.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  508.     break;
  509. default:
  510.     break;
  511. }
  512.     semGive (&pciMuteSem); /* mutual execlusion stop */
  513.     return (OK);
  514.     }
  515. /*******************************************************************************
  516. *
  517. * pciConfigOutLong - write one longword to the PCI configuration space
  518. *
  519. * This routine writes one longword to the PCI configuration space.
  520. *
  521. * RETURNS:
  522. * OK, or ERROR if this library is not initialized.
  523. *
  524. */
  525. STATUS pciConfigOutLong
  526.     (
  527.     int busNo, /* bus number */
  528.     int deviceNo, /* device number */
  529.     int funcNo, /* function number */
  530.     int address, /* address of the configuration space */
  531.     int data /* data written to the address */
  532.     )
  533.     {
  534.     if (pciLibInitStatus != OK) /* sanity check */
  535.         return (ERROR);
  536.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  537.     switch (pciConfigMech)
  538. {
  539. case PCI_MECHANISM_1:
  540.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  541.           (address & 0xfc) | 0x80000000);
  542.     PCI_OUT_LONG (pciConfigAddr1, data);
  543.     break;
  544. case PCI_MECHANISM_2:
  545.     PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
  546.     PCI_OUT_BYTE (pciConfigAddr1, busNo);
  547.     PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
  548.   (address & 0xfc)), data);
  549.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  550.     break;
  551. default:
  552.     break;
  553. }
  554.     semGive (&pciMuteSem); /* mutual execlusion stop */
  555.     return (OK);
  556.     }
  557. /*******************************************************************************
  558. *
  559. * pciSpecialCycle - generate a special cycle with a message
  560. *
  561. * This routine generates a special cycle with a message.
  562. *
  563. * RETURNS:
  564. * OK, or ERROR if this library is not initialized.
  565. *
  566. */
  567. STATUS pciSpecialCycle
  568.     (
  569.     int busNo, /* bus number */
  570.     int message /* data on AD[31:0] during the special cycle */
  571.     )
  572.     {
  573.     int deviceNo = 0x0000001f;
  574.     int funcNo = 0x00000007;
  575.     if (pciLibInitStatus != OK) /* sanity check */
  576.         return (ERROR);
  577.     semTake (&pciMuteSem, WAIT_FOREVER); /* mutual execlusion start */
  578.     switch (pciConfigMech)
  579. {
  580. case PCI_MECHANISM_1:
  581.     PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
  582.           0x80000000);
  583.     PCI_OUT_LONG (pciConfigAddr1, message);
  584.     break;
  585. case PCI_MECHANISM_2:
  586.     PCI_OUT_BYTE (pciConfigAddr0, 0xff);
  587.     PCI_OUT_BYTE (pciConfigAddr1, 0x00);
  588.     PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8)),
  589.   message);
  590.     PCI_OUT_BYTE (pciConfigAddr0, 0);
  591.     break;
  592. default:
  593.     break;
  594. }
  595.     semGive (&pciMuteSem); /* mutual execlusion stop */
  596.     return (OK);
  597.     }
  598. /*******************************************************************************
  599. *
  600. * pciInt - interrupt handler for shared PCI interrupt.
  601. *
  602. * This routine executes multiple interrupt handlers for a PCI interrupt.
  603. * Each interrupt handler must check the device dependent interrupt status bit
  604. * to determine the source of the interrupt, since it simply execute all
  605. * interrupt handlers in the link list.
  606. *
  607. * RETURNS: N/A
  608. *
  609. */
  610. VOID pciInt
  611.     (
  612.     int irq /* IRQ associated to the PCI interrupt */
  613.     )
  614.     {
  615.     PCI_INT_RTN *pRtn;
  616.     for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
  617.  pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
  618. (* pRtn->routine) (pRtn->parameter);
  619.     }
  620. /*******************************************************************************
  621. *
  622. * pciIntConnect - connect the interrupt handler to the PCI interrupt.
  623. *
  624. * This routine connects an interrupt handler to the PCI interrupt line(A - D).
  625. * Link list is created if multiple handlers are assigned to the single PCI
  626. * interrupt.
  627. *
  628. * RETURNS:
  629. * OK, or ERROR if the interrupt handler cannot be built.
  630. *
  631. */
  632. STATUS pciIntConnect
  633.     (
  634.     VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */
  635.     VOIDFUNCPTR routine,        /* routine to be called              */
  636.     int parameter               /* parameter to be passed to routine */
  637.     )
  638.     {
  639.     int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;
  640.     PCI_INT_RTN *pRtn;
  641.     int oldLevel;
  642.     if (pciLibInitStatus != OK)
  643. return (ERROR);
  644.     pRtn = (PCI_INT_RTN *)malloc (sizeof (PCI_INT_RTN));
  645.     if (pRtn == NULL)
  646. return (ERROR);
  647.     pRtn->routine   = routine;
  648.     pRtn->parameter = parameter;
  649.     oldLevel = intLock (); /* LOCK INTERRUPT */
  650.     dllAdd (&pciIntList[irq], &pRtn->node);
  651.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  652.     return (OK);
  653.     }
  654. /*******************************************************************************
  655. *
  656. * pciIntDisconnect - disconnect the interrupt handler from the PCI interrupt.
  657. *
  658. * This routine disconnects the interrupt handler from the PCI interrupt line.
  659. *
  660. * RETURNS:
  661. * OK, or ERROR if the interrupt handler cannot be removed.
  662. *
  663. */
  664. STATUS pciIntDisconnect
  665.     (
  666.     VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */
  667.     VOIDFUNCPTR routine         /* routine to be called              */
  668.     )
  669.     {
  670.     int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;
  671.     PCI_INT_RTN *pRtn;
  672.     int oldLevel;
  673.     if (pciLibInitStatus != OK)
  674. return (ERROR);
  675.     for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
  676.  pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
  677. {
  678. if (pRtn->routine == routine)
  679.     {
  680.     oldLevel = intLock (); /* LOCK INTERRUPT */
  681.     dllRemove (&pciIntList[irq], &pRtn->node);
  682.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  683.     free ((char *)pRtn);
  684.     return (OK);
  685.     }
  686. }
  687.     return (ERROR);
  688.     }