/***************************************************************************/ /* example_pio_dma.c * * Build: * $COMMONCC -o example_pio_dma example_pio_dma.c $VMELIBS * * Example for Programmed VME I/O in A32/D32 and * VME BLT-D32 DMA (if supported) with one channel. */ /***************************************************************************/ #include <stdio.h> #include <sys/types.h> #include "Vme.h" #define VME_PIO_ADDRESS 0x10000000 #define VME_PIO_SIZE (1024*1024) /* 1 MB */ #define VME_PIO_AM 0x09 /* Extended VME address */ #define VME_BLT_AM 0x0b /* BLT D32 */ #define BUFFER_SIZE (128*1024) /***************************************************************************/ main (int argc, char *argv[]) /*--------------------------- */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { u_long vme_address = VME_PIO_ADDRESS; int cid, offset, length, count; int *vme_base; int *buffer; /*.........................................................................*/ /* ----------------------------------------------------------------------- * Use a different VME base address if specified. */ if ((argc==2)&&(sscanf(argv[1],"%x",&vme_address)!=1)) { printf("Usage: %s <vme-base-address>\n",argv[0]); exit(1); } /* ----------------------------------------------------------------------- * Open a VME channel for Programmed I/O and DMA. */ cid = VmeOpenChannel ("pio_dma_2", "pio,dma"); if (cid < 0 ) exit(1); /* ----------------------------------------------------------------------- * Allocate and prepare some buffer space for DMA. With this buffer DMA * might be significantly faster using contiguous memory and locking the * buffer space in memory in advance. * * Note: This special function is not needed but if you call it ONLY * this buffer is allowed to be for DMA with this channel ! */ buffer = (int*)VmeAllocateMemory (cid, NULL, BUFFER_SIZE, Vme_MEMORY_FASTEST); if (buffer == NULL) exit(1); /* ----------------------------------------------------------------------- * Map VME address space for PIO and define the base address for the VME * copy function including DMA. * * Note: the address modifier and size is valid for PIO only! */ vme_base = (int*)VmeMapAddress (cid, vme_address, VME_PIO_SIZE, VME_PIO_AM); if (vme_base == NULL) exit(1); /* ----------------------------------------------------------------------- * You can do PIO like in example pio_1.c ... */ Vme_D32WRITE(vme_base, &vme_base[7], 0xdeadbeef); /* ----------------------------------------------------------------------- * ... and read/write data from/to VME with the specified offset and * length in bytes. * * Note: the functions return the number of bytes actually read or * written which can be less than requested if the transfer was * aborted (normally by a VME bus error). */ offset = 0x100; length = 0x10000; count = VmeRead (cid, offset, (char *)buffer, length); if (count != length) exit(1); count = VmeWrite (cid, offset, (char *)buffer, length); if (count != length) exit(1); /* ----------------------------------------------------------------------- * There are a few defaults you can modify with the VmeSetProperty() * function: * * 1. the address modifier to be used for the BLT (default=0x0b). */ VmeSetProperty(cid, Vme_SET_BLT_AM, 0x08); /* BLT D64 */ /* 2. the threshold lenght above which DMA will be performed. The setup * of a DMA introduces some overhead which could make the transfer * of small blocks quite slow. PIO is then the faster choice. * * Note: normally there is a good system dependent default but it * might be useful to enable or disable DMA. */ VmeSetProperty(cid, Vme_SET_DMA_THRESHOLD, 0x100); /* ----------------------------------------------------------------------- * Close Vme channel. Do not forget to call this function before * you exit otherwise you might get some trouble later. */ (void)VmeCloseChannel(cid); }