📄 vme_api.c
字号:
- DMA_VOFF_512US - DMA_VOFF_1024US - DMA_VOFF_2US - DMA_VOFF_4US - DMA_VOFF_8US */ void *data /* Pass in struct sigevent if this is a non-blocking call. Returns state of the DGCS register for blocking calls */ ){ /* Non-blocking DMAs are not currently supported by the new driver. */ if (DMA_BLOCKING & flags) { flags &= ~DMA_BLOCKING; } else { errno = EINVAL; return (-1); } /* Massage the flags to fit the new API */ if (0x00700000 & flags) { flags |= (0x0070000 & flags) >> 8; flags &= ~0x0070000; } /* The new Tundra Universe driver does not tolerate address modifiers with inconsistant data widths. i.e. The Universe chip generates MBLT cycles if the data width is 64-bit, whether you specified BLT's or not. For that reason, this function must fix the call parameters so old code does not fail this new check. */ switch (am) { case VME_A24UMB: case VME_A24SMB: case VME_A32UMB: case VME_A32SMB: dw = VME_D64; break; default: if (VME_D64 == dw) dw = VME_D32; } switch (dw) { case VME_D16: flags |= VME_DMA_DW_16; break; case VME_D32: flags |= VME_DMA_DW_32; break; case VME_D64: flags |= VME_DMA_DW_64; break; default: errno = EINVAL; return (-1); } /* The new driver does not return the DGCS register so we fake it out here. */ *(int *) data = UNIV_DGCS__DONE; if (0 > (vme_dma_read (bus_handle, handle, offset, addr, am, nelem * dw, flags))) { *(int *) data = UNIV_DGCS__VERR; return (-1); } return (0);}/*============================================================================ * Write data from the DMA buffer at offset to the specified VMEbus address */int /* Returns 0 on success or -1 on failure */vmeWriteDma (vme_dma_handle_t handle, /* Handle to allocated DMA memory */ uint64_t addr, /* Address on the VMEbust to read from */ unsigned long nelem, /* Number of elements of data width sized elements to read. */ vme_addr_mod_t am, /* VMEbus address modifier */ vme_dwidth_t dw, /* Transfer data width */ unsigned long offset, /* Offset into the DMA buffer */ unsigned int flags, /* The following constants may be OR'ed together to control the DMA operation: - DMA_LD64EN - enable 64-bit PCI transactions One of the following settings of the VON counter: - DMA_VON_UNITL_DONE - DMA_VON_256BYTE - DMA_VON_512BYTE - DMA_VON_1024BYTE - DMA_VON_2048BYTE - DMA_VON_4096BYTES - DMA_VON_8192BYTES - DMA_VON_16384BYTES One of the following settings of the VOFF counter: - DMA_VOFF_0US - DMA_VOFF_16US - DMA_VOFF_32US - DMA_VOFF_64US - DMA_VOFF_128US - DMA_VOFF_256US - DMA_VOFF_512US - DMA_VOFF_1024US - DMA_VOFF_2US - DMA_VOFF_4US - DMA_VOFF_8US */ void *data /* Pass in struct sigevent if this is a non-blocking call. Returns state of the DGCS register for blocking calls */ ){ /* Non-blocking DMAs are not currently supported by the new driver. */ if (DMA_BLOCKING & flags) { flags &= ~DMA_BLOCKING; } else { errno = EINVAL; return (-1); } /* Massage the flags to fit the new API */ if (0x00700000 & flags) { flags |= (0x0070000 & flags) >> 8; flags &= ~0x0070000; } /* The new Tundra Universe driver does not tolerate address modifiers with inconsistant data widths. i.e. The Universe chip generates MBLT cycles if the data width is 64-bit, whether you specified BLT's or not. For that reason, this function must fix the call parameters so old code does not fail this new check. */ switch (am) { case VME_A24UMB: case VME_A24SMB: case VME_A32UMB: case VME_A32SMB: dw = VME_D64; break; default: if (VME_D64 == dw) dw = VME_D32; } switch (dw) { case VME_D16: flags |= VME_DMA_DW_16; break; case VME_D32: flags |= VME_DMA_DW_32; break; case VME_D64: flags |= VME_DMA_DW_64; break; default: errno = EINVAL; return (-1); } /* The new driver does not return the DGCS register so we fake it out here. */ *(int *) data = UNIV_DGCS__DONE; if (0 > (vme_dma_write (bus_handle, handle, offset, addr, am, nelem * dw, flags))) { *(int *) data = UNIV_DGCS__VERR; return (-1); } return (0);}/***************************************************************************** * Install an interrupt handler */int /* 0 on success, -1 on failure */vmeInstallIntrHandler (vme_intr_lvl_t level, /* Interrupt level */ uint8_t vector, /* Interrupt vector, used for VMEbus interrupts only, otherwise use 0 */ unsigned int flags, /* One of the following: - V_BLOCKING, - V_SIGEVENT */ void *data /* For V_SIGEVENT this is an event of type struct sigaction. For V_BLOCKING, this is a pointer to the data value to be returned. For Mailbox interrupts, data is the data read from the mailbox register. For DMA interrupts, it is the value of the DGCS register. For VMEbus errors, it is the address of the access that caused the error */ ){ int index = UNIV_INTERRUPT_INDEX (level, vector); if (interrupt[index]) { errno = EBUSY; return (-1); } if ((SIGRTMAX >= flags) && (0 < flags)) { /* Handle legacy flags; Flags used to be the signal number. */ struct sigevent event; event.sigev_signo = flags; event.sigev_notify = SIGEV_SIGNAL; return (vme_interrupt_attach (bus_handle, &interrupt[index], level, vector, VME_INTERRUPT_SIGEVENT, &event)); } if (V_SIGEVENT == flags) return (vme_interrupt_attach (bus_handle, &interrupt[index], level, vector, VME_INTERRUPT_SIGEVENT, data)); return (vme_interrupt_attach (bus_handle, &interrupt[index], level, vector, VME_INTERRUPT_BLOCKING, data));}/***************************************************************************** * Uninstall an interrupt handler */int /* 0 on success, -1 on failure */vmeRemoveIntrHandler (vme_intr_lvl_t level, /* Interrupt level */ uint8_t vector /* Interrupt vector. Only used for VMEbus interrupts, otherwise pass 0 */ ){ int index = UNIV_INTERRUPT_INDEX (level, vector); int status; status = vme_interrupt_release (bus_handle, interrupt[index]); interrupt[index] = 0; return (status);}/***************************************************************************** * Cancel a blocking call to vmeInstallIntrHandler() */int /* 0 on success, -1 on failure */vmeCancelIntrHandler (vme_intr_lvl_t level, /* Interrupt level */ uint8_t vector /* Interrupt vector. Only used for VMEbus interrupts. Otherwise use 0 */ ){ return (vmeRemoveIntrHandler (level, vector));}/***************************************************************************** * Generate an interrupt onto the VMEbus */int /* 0 on success, -1 on failure */vmeGenerateIntr (vme_intr_lvl_t level, /* Interrupt level */ uint8_t vector /* Interrupt vector. */ ){ return (vme_interrupt_generate (bus_handle, level, vector));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -