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

VxWorks

开发平台:

C/C++

  1. /* usrUsbPciLib.c - USB specific PCI Functions */
  2. /* Copyright 1999-2000 Wind River Systems, Inc. */
  3. /*
  4. Modification history
  5. --------------------
  6. 01a,10feb00,wef  written 
  7. */
  8. /*
  9. DESCRIPTION
  10. This file defines platform-independent functions accessing PCI bus 
  11. capabilities.  These functions allow PCI device drivers to be written 
  12. independent of the underlying O/S's PCI access mechanisms.
  13. The name of each function in this group begins with "usb" to represent
  14. "Device Driver Services."
  15. */
  16. /* Includes */
  17. #include "string.h"
  18. #include "vxWorks.h"
  19. #include "sysLib.h"
  20. #include "cacheLib.h"
  21. #include "iv.h"
  22. #include "intLib.h"
  23. #include "drv/pci/pciConfigLib.h"     /* VxWorks PCI funcs */
  24. /* PLATFORM-DEPENDENT INCLUDES/DEFINITIONS */
  25. #if CPU == PPC604
  26. /* Power PC 604 (e.g., mcp750) */
  27. /* This is messy.  There is no standard vxWorks function to in/out from
  28. PCI I/O address space. So, we need to bring in some constants from the
  29. actual hardware-specific build. */
  30. #include "mv2600.h"
  31. /* Mappings for I/O and memory address translation (values from mv2600.h) */
  32. #define PCI_IO_OFFSET     CPU_PCI_ISA_IO_ADRS
  33. #define PCI_MEM_OFFSET     PCI2DRAM_BASE_ADRS
  34. #define PCI_MEMIO_OFFSET    (CPU_PCI_MEM_ADRS - PCI_MEM_ADRS)
  35. /* The mcp750 doesn't define sysInWord, sysInLong, sysOutWord, and
  36.  * sysOutLong. It includes the following entry points instead for which
  37.  * there is no vxWorks function prototype.  We include the following
  38.  * definitions in order to suppress compiler warnings.
  39.  */
  40. /* Map the "standard" vxworks I/O functions to the mcp750 equivalents */
  41. #define sysInWord(p) sysIn16(p)
  42. #define sysInLong(p) sysIn32(p)
  43. #define sysOutWord(p,d) sysOut16(p,d)
  44. #define sysOutLong(p,d) sysOut32(p,d)
  45. /* Interrupt enable/disable */
  46. #ifdef MCP750
  47. #define INTERRUPT_BASE ISA_INTERRUPT_BASE
  48. #else
  49. #define INTERRUPT_BASE EXT_INTERRUPT_BASE
  50. #endif
  51. #define IVEC(i) INUM_TO_IVEC ((int) ((i) + INTERRUPT_BASE))
  52. #define INT_CONNECT(intNo, func, param) 
  53.     intConnect (IVEC (intNo), (VOIDFUNCPTR) func, (int) param)
  54. #define INT_DISCONNECT(intNo, func, param)
  55. #define INT_ENABLE(i) intEnable ((i) + INTERRUPT_BASE)
  56. #define INT_DISABLE(i) intDisable ((i) + INTERRUPT_BASE)
  57. #elif     CPU == PENTIUM
  58. /* Pentium (e.g, PC Pentium) */
  59. #include "drv/pci/pciIntLib.h"
  60. /* Mappings for I/O and memory address translation */
  61. #define PCI_IO_OFFSET     0
  62. #define PCI_MEM_OFFSET     0
  63. #define PCI_MEMIO_OFFSET    0
  64. /* Interrupt enable/disable */
  65. #define INTERRUPT_BASE 0x20
  66. #define IVEC(i) INUM_TO_IVEC ((int) ((i) + INTERRUPT_BASE))
  67. #define INT_CONNECT(intNo, func, param) 
  68.     pciIntConnect (IVEC (intNo), (VOIDFUNCPTR) func, (int) param)
  69. #define INT_DISCONNECT(intNo, func, param) 
  70.     pciIntDisconnect (IVEC (intNo), (VOIDFUNCPTR) func)
  71. #define INT_ENABLE(i) sysIntEnablePIC (i)
  72. #define INT_DISABLE(i) sysIntDisablePIC (i)
  73. /* Unknown platform */
  74. #else
  75. #error "Unknown platform.  Must create platform mapping in usbPciLib.c."
  76. #endif /* #if CPU == xxxx */
  77. /* more includes */
  78. #include "usb/usbPlatform.h" /* Basic definitions */
  79. #include "usb/usbPciLib.h"     /* Our API */
  80. /* defines */
  81. /* Map I/O functions to underlying system functions. */
  82. #define OUR_PCI_IN_BYTE(a) sysInByte ((a) + PCI_IO_OFFSET)
  83. #define OUR_PCI_IN_WORD(a) sysInWord ((a) + PCI_IO_OFFSET)
  84. #define OUR_PCI_IN_DWORD(a) sysInLong ((a) + PCI_IO_OFFSET)
  85. #define OUR_PCI_OUT_BYTE(a,v) sysOutByte ((a) + PCI_IO_OFFSET, (v))
  86. #define OUR_PCI_OUT_WORD(a,v) sysOutWord ((a) + PCI_IO_OFFSET, (v))
  87. #define OUR_PCI_OUT_DWORD(a,v) sysOutLong ((a) + PCI_IO_OFFSET, (v))
  88. /* code tracks usage count for interrupts 0..MAX_INT_NO-1. */
  89. #define MAX_INT_NO 16
  90. /* locals */
  91. LOCAL UINT16 intUsage [MAX_INT_NO] = {0};
  92. /***************************************************************************
  93. *
  94. * usbPciClassFind - Locates PCI devices by class.
  95. *
  96. * A caller uses this function to locate a PCI device by its PCI class.
  97. * The caller must specify the <pciClass>, <subClass>, and <pgmIf> for the
  98. * device being sought. The function returns the first matching device
  99. * for <index> = 0, the second for <index> = 1, and so forth.  The
  100. * bus number, device number, and function number for the matching device 
  101. * are returned in the <pBusNo>, <pDeviceNo>, and <pFuncNo> buffers provided 
  102. * by the caller. 
  103. *
  104. *
  105. * RETURNS: TRUE if matching device found, FALSE if device not found.
  106. */
  107. BOOL usbPciClassFind
  108.     (
  109.     UINT8 pciClass, /* PCI device class */
  110.     UINT8 subClass, /* PCI device sub-class */
  111.     UINT8 pgmIf, /* Programming interface */
  112.     UINT16 index, /* Caller wants nth matching dev */
  113.     pUINT8 pBusNo, /* Bus number of matching dev */
  114.     pUINT8 pDeviceNo, /* Device number of matching dev */
  115.     pUINT8 pFuncNo /* Function number of matching dev */
  116.     )
  117.     {
  118.     int intBusNo; /* VxWorks returns "int" values */
  119.     int intDeviceNo;
  120.     int intFuncNo;
  121.     
  122.     /* Use the VxWorks PCI config. library to find a device within the
  123.     specified class. */
  124.     if (pciFindClass ((pciClass << 16) | (subClass << 8) | pgmIf, index,
  125. &intBusNo, &intDeviceNo, &intFuncNo) != OK)
  126. {
  127. return FALSE;
  128. }
  129.     else
  130. {
  131. if (pBusNo) *pBusNo = (UINT8) intBusNo;
  132. if (pDeviceNo) *pDeviceNo = (UINT8) intDeviceNo;
  133. if (pFuncNo) *pFuncNo = (UINT8) intFuncNo;
  134. }
  135.     return TRUE;
  136.     }
  137. /***************************************************************************
  138. *
  139. * usbPciByteGet - Returns a UINT8 configuration value
  140. *
  141. * This function returns the UINT8 value at offset <regOffset> from 
  142. * the PCI configuration space of the device identified by <busNo>, 
  143. * <deviceNo>, and <funcNo>.
  144. *
  145. * RETURNS: UINT8 value read from device configuration space
  146. */
  147. UINT8 usbPciByteGet 
  148.     (
  149.     UINT8 busNo, /* Bus number of device */
  150.     UINT8 deviceNo, /* Device number of device */
  151.     UINT8 funcNo, /* Function number of device */
  152.     UINT16 regOffset /* Offset into PCI config space */
  153.     )
  154.     {
  155.     UINT8 value;
  156.     if (pciConfigInByte (busNo, deviceNo, funcNo, regOffset, &value) != OK)
  157. return 0;
  158.     return value;
  159.     }
  160. /***************************************************************************
  161. *
  162. * usbPciWordGet - Returns a UINT16 configuration value
  163. *
  164. * This function returns the UINT16 value at offset <regOffset> from 
  165. * the PCI configuration space of the device identified by <busNo>, 
  166. * <deviceNo>, and <funcNo>.
  167. *
  168. * NOTE: This function adjusts for big vs. little endian environments.
  169. *
  170. * RETURNS: UINT16 value read from device configuration space
  171. */
  172. UINT32 usbPciWordGet
  173.     (
  174.     UINT8 busNo, /* Bus number of device */
  175.     UINT8 deviceNo, /* Device number of device */
  176.     UINT8 funcNo, /* Function number of device */
  177.     UINT16 regOffset /* Offset into PCI config space */
  178.     )
  179.     {
  180.     UINT16 value;
  181.     if (pciConfigInWord (busNo, deviceNo, funcNo, regOffset, &value) != OK)
  182. return 0;
  183.     return value;
  184.     }
  185. /***************************************************************************
  186. *
  187. * usbPciDwordGet - Returns a UINT32 configuration value
  188. *
  189. * This function returns the UINT32 value at offset <regOffset> from 
  190. * the PCI configuration space of the device identified by <busNo>, 
  191. * <deviceNo>, and <funcNo>.
  192. *
  193. * NOTE: This function adjusts for big vs. little endian environments.
  194. *
  195. * RETURNS: UINT32 value read from device configuration space
  196. */
  197. UINT32 usbPciDwordGet
  198.     (
  199.     UINT8 busNo, /* Bus number of device */
  200.     UINT8 deviceNo, /* Device number of device */
  201.     UINT8 funcNo, /* Function number of device */
  202.     UINT16 regOffset /* Offset into PCI config space */
  203.     )
  204.     {
  205.     UINT32 value;
  206.     if (pciConfigInLong (busNo, deviceNo, funcNo, regOffset, &value) != OK)
  207. return 0;
  208.     return value;
  209.     }
  210. /***************************************************************************
  211. *
  212. * usbPciConfigHeaderGet - Reads a device's PCI configuration header
  213. *
  214. * This function reads the PCI configuration header for the device
  215. * identified by <busNo>, <deviceNo>, and <funcNo>.  The configuration
  216. * header is stored in the <pCfgHdr> buffer provided by the caller.
  217. *
  218. * This function initializes the <pCfgHdr> structure to zeros.  Any 
  219. * fields which cannot be read from the device's configuration header 
  220. * will remain zero upon return.  This function does not attempt to read
  221. * fields defined as "reserved" in the PCI configuration header.
  222. *
  223. * RETURNS: N/A
  224. */
  225. VOID usbPciConfigHeaderGet
  226.     (
  227.     UINT8 busNo, /* Bus number of device */
  228.     UINT8 deviceNo, /* Device number of device */
  229.     UINT8 funcNo, /* Function number of device */
  230.     pPCI_CFG_HEADER pCfgHdr /* Buffer provided by caller */
  231.     )
  232.     {
  233.     int i;
  234.     /* Do nothing if CfgHdr is NULL */
  235.     if (pCfgHdr == NULL)
  236. return;
  237.     /* Initialize the buffer to zeros. */
  238.     memset (pCfgHdr, 0, sizeof (*pCfgHdr));
  239.     /* Read and store each field in the PCI configuration header. */
  240.     pCfgHdr->vendorId = usbPciWordGet (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID);
  241.     pCfgHdr->deviceId = usbPciWordGet (busNo, deviceNo, funcNo, PCI_CFG_DEVICE_ID);
  242.     pCfgHdr->command = usbPciWordGet (busNo, deviceNo, funcNo, PCI_CFG_COMMAND);
  243.     pCfgHdr->status = usbPciWordGet (busNo, deviceNo, funcNo, PCI_CFG_STATUS);
  244.     pCfgHdr->revisionId = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_REVISION);
  245.     pCfgHdr->pgmIf = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_PROGRAMMING_IF);
  246.     pCfgHdr->subClass = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_SUBCLASS);
  247.     pCfgHdr->pciClass = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_CLASS);
  248.     pCfgHdr->cacheLineSize = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_CACHE_LINE_SIZE);
  249.     pCfgHdr->latencyTimer = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_LATENCY_TIMER);
  250.     pCfgHdr->headerType = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE);
  251.     pCfgHdr->bist = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_BIST);
  252.     for (i = 0; i < PCI_CFG_NUM_BASE_REG; i++)
  253. pCfgHdr->baseReg [i] = usbPciDwordGet (busNo, deviceNo, funcNo, 
  254.     PCI_CFG_BASE_ADDRESS_0 + i * sizeof (UINT32));
  255.     pCfgHdr->romBase = usbPciDwordGet (busNo, deviceNo, funcNo, PCI_CFG_EXPANSION_ROM);
  256.     pCfgHdr->intLine = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_DEV_INT_LINE);
  257.     pCfgHdr->intPin = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_DEV_INT_PIN);
  258.     pCfgHdr->minGrant = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_MIN_GRANT);
  259.     pCfgHdr->maxLatency = usbPciByteGet (busNo, deviceNo, funcNo, PCI_CFG_MAX_LATENCY);
  260.     }
  261. /***************************************************************************
  262. *
  263. * usbPciByteIn - input a byte from PCI I/O space
  264. *
  265. * Inputs a byte from a PCI I/O address <address>.
  266. *
  267. * RETURNS: byte input from i/o address
  268. */
  269. UINT8 usbPciByteIn
  270.     (
  271.     UINT32 address /* PCI I/O address */
  272.     )
  273.     {
  274.     return OUR_PCI_IN_BYTE (address);
  275.     }
  276. /***************************************************************************
  277. *
  278. * usbPciWordIn - input a word from PCI I/O space
  279. *
  280. * Inputs a word from a PCI I/O address <address>.
  281. *
  282. * NOTE: This function adjusts for big vs. little endian environments.
  283. *
  284. * RETURNS: word input from i/o address
  285. */
  286. UINT16 usbPciWordIn
  287.     (
  288.     UINT32 address /* PCI I/O address */
  289.     )
  290.     {
  291.     UINT16 w = OUR_PCI_IN_WORD (/*(UINT16 *)*/address);
  292.     return FROM_LITTLEW (w);
  293.     }
  294. /***************************************************************************
  295. *
  296. * usbPciDwordIn - input a dword from PCI I/O space
  297. *
  298. * Inputs a dword from a PCI I/O address <address>.
  299. *
  300. * NOTE: This function adjusts for big vs. little endian environments.
  301. *
  302. * RETURNS: dword input from i/o address
  303. */
  304. UINT32 usbPciDwordIn
  305.     (
  306.     UINT32 address /* PCI I/O address */
  307.     )
  308.     {
  309.     UINT32 l = OUR_PCI_IN_DWORD (/*(UINT32 *)*/address);
  310.     return FROM_LITTLEL (l);
  311.     }
  312. /***************************************************************************
  313. *
  314. * usbPciByteOut - output a byte to PCI I/O space
  315. *
  316. * Outputs <value> to the PCI I/O address <address>.
  317. *
  318. * RETURNS: N/A
  319. */
  320. VOID usbPciByteOut
  321.     (
  322.     UINT32 address, /* PCI I/O address */
  323.     UINT8 value /* value */
  324.     )
  325.     {
  326.     OUR_PCI_OUT_BYTE (address, value);
  327.     CACHE_PIPE_FLUSH ();
  328.     }
  329. /***************************************************************************
  330. *
  331. * usbPciWordOut - outputs a word to PCI I/O space
  332. *
  333. * Outputs <value> to the PCI I/O address <address>.
  334. *
  335. * NOTE: This function adjusts for big vs. little endian environments.
  336. *
  337. * RETURNS: N/A
  338. */
  339. VOID usbPciWordOut
  340.     (
  341.     UINT32 address, /* PCI I/O address */
  342.     UINT16 value /* value */
  343.     )
  344.     {
  345.     UINT16 w = TO_LITTLEW (value);
  346.     OUR_PCI_OUT_WORD (/*(UINT16 *)*/address, w);
  347.     CACHE_PIPE_FLUSH ();
  348.     }
  349. /***************************************************************************
  350. *
  351. * usbPciDwordOut - outputs a dword to PCI I/O space
  352. *
  353. * Outputs <value> to the PCI I/O address <address>.
  354. *
  355. * NOTE: This function adjusts for big vs. little endian environments.
  356. *
  357. * RETURNS: N/A
  358. */
  359. VOID usbPciDwordOut
  360.     (
  361.     UINT32 address, /* PCI I/O address */
  362.     UINT32 value /* value */
  363.     )
  364.     {
  365.     UINT32 l = TO_LITTLEL (value);
  366.     OUR_PCI_OUT_DWORD (/*(UINT32 *)*/address, l);
  367.     CACHE_PIPE_FLUSH ();
  368.     }
  369. /***************************************************************************
  370. *
  371. * usbPciMemioOffset - Return PCI MEMIO to CPU MEMIO offset
  372. *
  373. * For memory-mapped I/O, the CPU's view of a memory address may not be the
  374. * same as that programmed into the base address register of a PCI adapter.
  375. * The CPU should add the value returned by this function to the BAR in order
  376. * to produce the correct CPU-visible memory address.
  377. *
  378. * RETURNS: PCI_MEMIO_OFFSET
  379. */
  380. UINT32 usbPciMemOffset (void)
  381.     {
  382.     return PCI_MEMIO_OFFSET;
  383.     }
  384. /***************************************************************************
  385. *
  386. * usbMemToPci - Convert a memory address to a PCI-reachable memory address
  387. *
  388. * Converts <pMem> to an equivalent 32-bit memory address visible from the 
  389. * PCI bus.  This conversion is necessary to allow PCI bus masters to address
  390. * the same memory viewed by the processor.
  391. *
  392. * RETURNS: converted memory address
  393. */
  394. UINT32 usbMemToPci
  395.     (
  396.     pVOID pMem /* memory address to convert */
  397.     )
  398.     {
  399.     pVOID pPhys;
  400.     
  401.     /* The conversion is a two-step process.  First, we need to convert the
  402.      * logical processor address (virtual) to a physical address.  Then, we
  403.      * convert the physical address to one which can be seen from the PCI
  404.      * bus.
  405.      */
  406.     pPhys = CACHE_DRV_VIRT_TO_PHYS (&cacheUserFuncs, pMem);
  407.     return ((UINT32) pPhys) + PCI_MEM_OFFSET;
  408.     }
  409. /***************************************************************************
  410. *
  411. * usbPciToMem - Convert a PCI-reachable address to a CPU-reachable pointer
  412. *
  413. * Converts <pciAdrs> to an equivalent CPU memory address.  
  414. *
  415. * RETURNS: pointer to PCI memory
  416. */
  417. pVOID usbPciToMem
  418.     (
  419.     UINT32 pciAdrs /* 32-bit PCI address to be converted */
  420.     )
  421.     {
  422.     return CACHE_DRV_PHYS_TO_VIRT (&cacheUserFuncs, 
  423. (void *) (pciAdrs - PCI_MEM_OFFSET));
  424.     }
  425. /***************************************************************************
  426. *
  427. * usbPciMemInvalidate - Invalidate cache for a region of memory
  428. *
  429. * When another bus master, such as a PCI bus master, writes to memory, the
  430. * cache may need to be invalidated for that region of memory.
  431. *
  432. * NOTE: Returns immediately if size == 0.
  433. *
  434. * RETURNS: N/A
  435. */
  436. VOID usbPciMemInvalidate
  437.     (
  438.     pVOID pMem, /* base of memory region to invalidate */
  439.     UINT32 size /* size of region to invalidate */
  440.     )
  441.     {
  442.     if (size != 0)
  443. CACHE_USER_INVALIDATE (pMem, size);
  444.     }
  445. /***************************************************************************
  446. *
  447. * usbPciMemFlush - Flush a region of memory through the cache
  448. *
  449. * In systems which implement a non-write-thru cache, the processor may have
  450. * written data to memory which has not yet been flushed to the actual system
  451. * memory.  Before other bus masters may interrogate this memory, it may be
  452. * necessary to flush the cache.
  453. *
  454. * NOTE: Returns immediately if size == 0.
  455. *
  456. * RETURNS: N/A
  457. */
  458. VOID usbPciMemFlush
  459.     (
  460.     pVOID pMem, /* base of memory region to invalidate */
  461.     UINT32 size /* size of region to invalidate */
  462.     )
  463.     {
  464.     if (size != 0)
  465. CACHE_USER_FLUSH (pMem, size);
  466.     }
  467. /***************************************************************************
  468. *
  469. * usbPciIntConnect - Connect to a interrupt vector
  470. *
  471. * Connects the <func> to the interrupt number <intNo>. <param> is an
  472. * application-specific value which will be passed to <func> each time
  473. * the interrupt handler is invoked.  
  474. *
  475. * RETURNS: OK, or ERROR if unable to connect/enable interrupt
  476. */
  477. STATUS usbPciIntConnect
  478.     (
  479.     INT_HANDLER_PROTOTYPE func,     /* new interrupt handler */
  480.     pVOID param,     /* parameter for int handler */
  481.     UINT16 intNo     /* interrupt vector number */
  482.     )
  483.     {
  484.     if (INT_CONNECT (intNo, func, param) != OK)
  485. return ERROR;
  486.     if (INT_ENABLE (intNo) != OK)
  487. {
  488. INT_DISCONNECT (intNo, func, param);
  489. return ERROR;
  490. }
  491.     if (intNo < MAX_INT_NO) 
  492. intUsage [intNo]++;
  493.     return OK;
  494.     }
  495. /***************************************************************************
  496. *
  497. * usbPciIntDisconnect - Removes an interrupt handler
  498. *
  499. * Removes an interrupt handler installed by usbPciIntConnect().  <func>,
  500. * <param>, and <intNo> must match the corresponding parameters from an earlier 
  501. * call to usbPciIntConnect().
  502. *
  503. * RETURNS: N/A
  504. */
  505. VOID usbPciIntRestore
  506.     (
  507.     INT_HANDLER_PROTOTYPE func,     /* int handler to be removed */
  508.     pVOID param,     /* parameter for int handler */
  509.     UINT16 intNo     /* interrupt vector number */
  510.     )
  511.     {
  512.     if (intNo >= MAX_INT_NO || 
  513. (intUsage [intNo] != 0 && --intUsage [intNo] == 0))
  514. {
  515. INT_DISABLE (intNo);
  516. }
  517.     INT_DISCONNECT (intNo, func, param);
  518.     }