gefvme.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  * Name:         gefvme.c
00003  * Created by:   Konstantin Olchanski, Pierre-Andre Amaudruz
00004  *
00005  * Contents:     VME interface for the GE FANUC (VMIC) VME board processor
00006  *               using gefvme Linux driver.
00007  *
00008  *  $Id$
00009  *
00010 *********************************************************************/
00011 
00012 //#define _XOPEN_SOURCE 500
00013 #define  _GNU_SOURCE 1
00014 
00015 #include <stdio.h>
00016 #include <stdint.h>
00017 #include <string.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <assert.h>
00021 #include <fcntl.h>
00022 #include <errno.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <sys/ioctl.h>
00026 #include <sys/mman.h>
00027 
00028 #include "gefvme.h"
00029 
00030 #include "vmedrv.h"
00031 
00032 #define MAX_VME_SLOTS 7
00033 
00034 typedef struct {
00035   int          handle;
00036   int              am;
00037   mvme_size_t  nbytes;
00038   void          *addr;
00039   mvme_addr_t     low;
00040   mvme_addr_t    high;
00041   int           valid;
00042 } VME_TABLE;
00043 
00044 /********************************************************************/
00045 /**
00046 VME Memory map, uses the driver MVME_INTERFACE for storing the map information.
00047 @param *mvme VME structure
00048 @param vme_addr source address (VME location).
00049 @param n_bytes  data to write
00050 @return MVME_SUCCESS, MVME_ACCESS_ERROR
00051 */
00052 static int gefvme_openWindow(MVME_INTERFACE *mvme, int am, mvme_addr_t vme_addr, mvme_size_t n_bytes, int* pwindow, char** paddr)
00053 {
00054   int j;
00055   VME_TABLE *table;
00056   char devname[256];
00057   int fd;
00058   struct  vmeOutWindowCfg conf;
00059   int status;
00060   char* amode = "(unknown)";
00061   
00062   table = (VME_TABLE *) mvme->table;
00063 
00064   if (1)
00065     {
00066       /* Find new slot */
00067       for (j=0; j<MAX_VME_SLOTS; j++)
00068         if (!table[j].valid)
00069           {
00070             /* Create a new window */
00071             
00072             sprintf(devname, "/dev/vme_m%d", j);
00073             fd = open(devname, O_RDWR);
00074             if (fd < 0) {
00075               if (errno == ENXIO) {
00076                 fprintf(stderr,"gefvme_openWindow: VME driver not present: Cannot open VME device \'%s\', errno %d (%s)\n", devname, errno, strerror(errno));
00077                 exit(1);
00078               }
00079               if (errno != EBUSY)
00080                 fprintf(stderr,"gefvme_openWindow: Cannot open VME device \'%s\', errno %d (%s)\n", devname, errno, strerror(errno));
00081               continue;
00082             }
00083             
00084             break;
00085           }
00086     }
00087   else
00088     {
00089       // always use slot 0
00090 
00091       j = 2;
00092 
00093       fd = table[j].handle;
00094 
00095       if (!table[j].valid)
00096         {
00097           /* Create a new window */
00098           
00099           sprintf(devname, "/dev/vme_m%d", j);
00100           fd = open(devname, O_RDWR);
00101           assert(fd >= 0);
00102         }
00103     }
00104 
00105   printf("gefvme_openWindow: Slot %d, VME addr 0x%08x, am 0x%02x, size 0x%08x %d\n", j, vme_addr, table[j].am, n_bytes, n_bytes);
00106         
00107   if (j >= MAX_VME_SLOTS) {
00108     /* No more slot available */
00109     fprintf(stderr,"gefvme_openWindow: All VME slots are in use!\n");
00110     assert(!"Cannot continue!\n");
00111     return MVME_ACCESS_ERROR;
00112   }
00113 
00114   table[j].am     = ((am == 0) ? MVME_AM_DEFAULT : am);
00115   table[j].handle = fd;
00116 
00117   memset(&conf, 0, sizeof(conf));
00118 
00119   switch (table[j].am)
00120     {
00121     default:
00122       fprintf(stderr,"gefvme_openWindow: Do not know how to handle VME AM 0x%x\n", table[j].am);
00123       abort();
00124       return MVME_ACCESS_ERROR;
00125     case MVME_AM_A16_SD:
00126     case MVME_AM_A16_ND:
00127       vme_addr = 0;
00128       n_bytes = (1<<16);
00129       conf.addrSpace = VME_A16;       /*  Address Space */
00130       conf.userAccessType = VME_USER; /*  User/Supervisor Access Type */
00131       conf.dataAccessType = VME_DATA; /*  Data/Program Access Type */
00132       amode = "A16";
00133       break;
00134     case MVME_AM_A24:
00135     case MVME_AM_A24_ND:
00136       vme_addr = 0;
00137       n_bytes = (1<<24);
00138       conf.addrSpace = VME_A24;       /*  Address Space */
00139       conf.userAccessType = VME_USER; /*  User/Supervisor Access Type */
00140       conf.dataAccessType = VME_DATA; /*  Data/Program Access Type */
00141       amode = "A24";
00142       break;
00143     case MVME_AM_A32_ND:
00144     case MVME_AM_A32_SD:
00145       //n_bytes = 0x01000000;
00146       n_bytes = 0x00800000;
00147       {
00148         char* env = getenv("GEFVME_A32_SIZE");
00149         if (env)
00150           {
00151             n_bytes = strtoul(env, NULL, 0);
00152             fprintf(stderr,"gefvme: A32 window size set to 0x%x\n", n_bytes);
00153           }
00154       }
00155       vme_addr = vme_addr - vme_addr%n_bytes;
00156       conf.addrSpace = VME_A32;       /*  Address Space */
00157       conf.userAccessType = VME_USER; /*  User/Supervisor Access Type */
00158       conf.dataAccessType = VME_DATA; /*  Data/Program Access Type */
00159       amode = "A32";
00160       break;
00161     }
00162 
00163   table[j].low    = vme_addr;
00164   table[j].nbytes = n_bytes;
00165 
00166   table[j].addr   = NULL;
00167 
00168   conf.windowNbr = j;    /*  Window Number */
00169   conf.windowEnable = 1; /*  State of Window */
00170   conf.pciBusAddrU = 0;  /*  Start Address on the PCI Bus */
00171   conf.pciBusAddrL = 0;  /*  Start Address on the PCI Bus */
00172   conf.windowSizeU = 0;           /*  Window Size */
00173   conf.windowSizeL = n_bytes;     /*  Window Size */
00174   conf.xlatedAddrU = 0;           /*  Starting Address on the VMEbus */
00175   conf.xlatedAddrL = vme_addr;    /*  Starting Address on the VMEbus */
00176   conf.bcastSelect2esst = 0;      /*  2eSST Broadcast Select */
00177   conf.wrPostEnable = 0;          /*  Write Post State */
00178   conf.prefetchEnable = 0; /*  Prefetch Read Enable State */
00179   conf.prefetchSize = 0;   /*  Prefetch Read Size (in Cache Lines) */
00180   conf.xferRate2esst = VME_SSTNONE;  /*  2eSST Transfer Rate */
00181   conf.maxDataWidth  = VME_D32;      /*  Maximum Data Width */
00182   conf.xferProtocol  = 0; // VME_SCT;   /*  Transfer Protocol */
00183   conf.reserved = 0;       /* For future use */
00184 
00185   status = ioctl(fd, VME_IOCTL_SET_OUTBOUND, &conf);
00186   if (status != 0) {
00187     fprintf(stderr,"gefvme_openWindow: cannot VME_IOCTL_SET_OUTBOUND, errno %d (%s)\n", errno, strerror(errno));
00188     abort();
00189     return MVME_ACCESS_ERROR;
00190   }
00191 
00192   void* addr = mmap(NULL, n_bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
00193 
00194   if (addr == (void*)(-1)) {
00195     fprintf(stderr,"gefvme_openWindow: cannot mmap() VME address space, errno %d (%s)\n", errno, strerror(errno));
00196     abort();
00197     return MVME_ACCESS_ERROR;
00198   }
00199 
00200   table[j].addr = addr;
00201 
00202   fprintf(stderr, "gefvme_openWindow: Configured window %d VME AM 0x%02x %s addr 0x%08x size 0x%08x fd %d\n", j, table[j].am, amode, (int)vme_addr, (int)n_bytes, table[j].handle);
00203 
00204   table[j].valid = 1;
00205   table[j].high  = (table[j].low + table[j].nbytes);
00206 
00207   if (pwindow)
00208     *pwindow = j;
00209 
00210   if (paddr)
00211     *paddr = addr;
00212   
00213   return MVME_SUCCESS;
00214 }
00215 
00216 /********************************************************************/
00217 /**
00218 Retrieve mapped address from mapped table.
00219 Check if the given address belongs to an existing map. If not will
00220 create a new map based on the address, current address modifier and
00221 the given size in bytes.
00222 @param *mvme VME structure
00223 @param  nbytes requested transfer size.
00224 @return MVME_SUCCESS, ERROR
00225 */
00226 static int gefvme_mapcheck(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t n_bytes, int *pfd, int *poffset, char **paddr)
00227 {
00228   int status;
00229   int j;
00230   VME_TABLE *table;
00231   table = (VME_TABLE *) mvme->table;
00232 
00233   /* Look for existing mapping */
00234 
00235   for (j=0; j<MAX_VME_SLOTS; j++)
00236     if (table[j].valid) {    /* Check for the proper am */
00237       if (mvme->am != table[j].am)
00238         continue;
00239       /* Check the vme address range */
00240       if ((vme_addr >= table[j].low) && ((vme_addr+n_bytes) < table[j].high)) {
00241         /* valid range */
00242         break;
00243       }
00244     }
00245 
00246   /* Create a new mapping if needed */
00247 
00248   if (j>=MAX_VME_SLOTS) {
00249     status = gefvme_openWindow(mvme, mvme->am, vme_addr, n_bytes, &j, NULL);
00250     if (status != MVME_SUCCESS)
00251       return status;
00252   }
00253 
00254   if (pfd)
00255     *pfd = table[j].handle;
00256   if (poffset)
00257     *poffset = vme_addr - table[j].low;
00258   if (paddr)
00259     *paddr = table[j].addr;
00260 
00261   return MVME_SUCCESS;
00262 }
00263 
00264 // gefvme specific functions
00265 
00266 char* gefvme_get_a16(MVME_INTERFACE *mvme)
00267 {
00268   char* addr;
00269   int status = gefvme_openWindow(mvme, MVME_AM_A16, 0, 0x10000, NULL, &addr);
00270   if (status != MVME_SUCCESS)
00271     return NULL;
00272   return addr;
00273 }
00274 
00275 char* gefvme_get_a24(MVME_INTERFACE *mvme)
00276 {
00277   char* addr;
00278   int status = gefvme_openWindow(mvme, MVME_AM_A24, 0, 0x1000000, NULL, &addr);
00279   if (status != MVME_SUCCESS)
00280     return NULL;
00281   return addr;
00282 }
00283 
00284 char* gefvme_get_a32(MVME_INTERFACE *mvme, uint32_t vmeaddr, int size)
00285 {
00286   char* addr;
00287   int status = gefvme_openWindow(mvme, MVME_AM_A32, vmeaddr, size, NULL, &addr);
00288   if (status != MVME_SUCCESS)
00289     return NULL;
00290   return addr;
00291 }
00292 
00293 int gefvme_dma_debug   = 0;
00294 
00295 static int makeDmaPacket(vmeDmaPacket_t *pkt, int blt_mode, int am, uint32_t vme_addr, char* dst_addr, int nbytes)
00296 {
00297 
00298   memset(pkt, 0, sizeof(*pkt));
00299   
00300   pkt->maxPciBlockSize = 16*1024;
00301   pkt->maxVmeBlockSize = 16*1024;
00302   pkt->byteCount = nbytes;
00303   pkt->srcBus = VME_DMA_VME;
00304   pkt->srcAddr = vme_addr;
00305   pkt->srcAddrU = 0; // limited to A24 and A32. No A64, please!
00306   
00307   switch (blt_mode)
00308     {
00309     case MVME_BLT_BLT32:
00310       assert(vme_addr%4 == 0);
00311       assert(nbytes%4 == 0);
00312       pkt->srcVmeAttr.maxDataWidth = VME_D32;
00313       pkt->srcVmeAttr.xferProtocol = VME_BLT;
00314       break;
00315     case MVME_BLT_MBLT64:
00316     case MVME_AM_A24_SMBLT:
00317     case MVME_AM_A24_NMBLT:
00318     case MVME_AM_A32_SMBLT:
00319     case MVME_AM_A32_NMBLT:
00320       assert(vme_addr%8 == 0);
00321       assert(nbytes%8 == 0);
00322       //pkt->srcVmeAttr.maxDataWidth = VME_D64;
00323       pkt->srcVmeAttr.maxDataWidth = VME_D32;
00324       pkt->srcVmeAttr.xferProtocol = VME_MBLT;
00325       break;
00326     default:
00327       fprintf(stderr,"makeDmaPacket: Unknown mvme->blt_mode DMA mode %d\n", blt_mode);
00328       assert(!"makeDmaPacket: Unknown DMA mode!");
00329     }
00330   
00331   switch (am)
00332     {
00333     default:
00334       fprintf(stderr,"makeDmaPacket: Unknown mvme->am VMA AM 0x%x\n", am);
00335       assert(!"makeDmaPacket: Unknown VME AM DMA mode!");
00336       return MVME_ACCESS_ERROR;
00337     case MVME_AM_A24:
00338     case MVME_AM_A24_ND:
00339     case MVME_AM_A24_SMBLT:
00340     case MVME_AM_A24_NMBLT:
00341       pkt->srcVmeAttr.addrSpace = VME_A24;
00342       break;
00343     case MVME_AM_A32_ND:
00344     case MVME_AM_A32_SD:
00345     case MVME_AM_A32_SMBLT:
00346     case MVME_AM_A32_NMBLT:
00347       pkt->srcVmeAttr.addrSpace = VME_A32;
00348       break;
00349     }
00350   
00351   //pkt->srcVmeAttr.userAccessType = VME_SUPER;
00352   pkt->srcVmeAttr.userAccessType = VME_USER;
00353   pkt->srcVmeAttr.dataAccessType = VME_DATA;
00354   pkt->dstBus = VME_DMA_USER;
00355   if (sizeof(dst_addr) == sizeof(uint32_t))
00356      {
00357         /* 32-bit addresses */
00358         pkt->dstAddr  = (uint32_t)dst_addr;
00359         pkt->dstAddrU = 0;
00360      }
00361   else
00362      {
00363         /* 64-bit addresses */
00364         pkt->dstAddr  = 0xFFFFFFFF & ((uint64_t)dst_addr);
00365         pkt->dstAddrU = 0xFFFFFFFF & ((uint64_t)dst_addr)>>32;
00366      }
00367 
00368   //printf("dst_addr: %p, addrL: 0x%08x, addrU: 0x%08x\n", dst_addr, pkt->dstAddr, pkt->dstAddrU);
00369 
00370   pkt->dstVmeAttr.maxDataWidth = 0;
00371   pkt->dstVmeAttr.addrSpace = 0;
00372   pkt->dstVmeAttr.userAccessType = 0;
00373   pkt->dstVmeAttr.dataAccessType = 0;
00374   pkt->dstVmeAttr.xferProtocol = 0;
00375   
00376   pkt->vmeDmaStatus = gefvme_dma_debug;
00377 
00378   return MVME_SUCCESS;
00379 }
00380 
00381 static int runDma(int channel, vmeDmaPacket_t *pkt)
00382 {
00383   char devnode[256];
00384   int status, fd, xerrno;
00385 
00386   sprintf(devnode, "/dev/vme_dma%d", channel);
00387   fd = open(devnode, 0);
00388   if (fd < 0) {
00389     fprintf(stderr,"gefvme::runDma: Cannot open VME device \'%s\', errno %d (%s)\n", devnode, errno, strerror(errno));
00390     return -errno;
00391   }
00392 
00393   errno  = 0;
00394   status = ioctl(fd, VME_IOCTL_START_DMA, pkt);
00395   xerrno = errno;
00396 
00397   close(fd);
00398 
00399   if (status < 0)
00400     return -xerrno;
00401 
00402   return 0;
00403 }
00404 
00405 int gefvme_dma_channel = 0;
00406 
00407 void  gefvme_set_dma_debug(int debug)
00408 {
00409   gefvme_dma_debug = debug;
00410 }
00411 
00412 void  gefvme_set_dma_channel(int channel)
00413 {
00414   assert(channel>=0 && channel<=1);
00415   gefvme_dma_channel = channel;
00416 }
00417 
00418 int gefvme_read_dma_multiple(MVME_INTERFACE *mvme, int nseg, void* dstaddr[], const mvme_addr_t vmeaddr[], int nbytes[])
00419 {
00420   int i;
00421   int xerrno;
00422   vmeDmaPacket_t pkt[nseg];
00423   for (i=0; i<nseg; i++)
00424     {
00425       if (gefvme_dma_debug)
00426         printf("packet %p+%d, blt %d, am 0x%x, vmeaddr 0x%x, dstaddr %p, nbytes %d\n",  pkt+i, sizeof(vmeDmaPacket_t), mvme->blt_mode, mvme->am, vmeaddr[i], dstaddr[i], nbytes[i]);
00427       makeDmaPacket(pkt+i, mvme->blt_mode, mvme->am, vmeaddr[i], dstaddr[i], nbytes[i]);
00428       pkt[i].pNextPacket = pkt+i+1;
00429     }
00430   pkt[nseg-1].pNextPacket = NULL;
00431 
00432   xerrno = runDma(gefvme_dma_channel, pkt);
00433 
00434   if (xerrno < 0) {
00435     fprintf(stderr,"gefvme_read_dma_multiple: ioctl(VME_IOCTL_START_DMA) errno %d (%s)\n", -xerrno, strerror(-xerrno));
00436     return MVME_ACCESS_ERROR;
00437   }
00438 
00439   if (pkt[0].vmeDmaStatus != 0x02000000) {
00440     fprintf(stderr,"mvme_read_dma_multiple: ioctl(VME_IOCTL_START_DMA) returned vmeDmaStatus 0x%08x\n", pkt[0].vmeDmaStatus);
00441     return MVME_ACCESS_ERROR;
00442   }
00443   
00444   return MVME_SUCCESS;
00445 }
00446 
00447 /********************************************************************/
00448 /**
00449 Open a VME channel
00450 One bus handle per crate.
00451 @param *mvme     VME structure.
00452 @param index    VME interface index
00453 @return MVME_SUCCESS, ERROR
00454 */
00455 int mvme_open(MVME_INTERFACE **mvme, int index)
00456 {
00457   /* index can be only 0 for VMIC */
00458   if (index != 0) {
00459     fprintf(stderr,"mvme_open: invalid index value %d, only 0 is permitted\n", index);
00460     return MVME_INVALID_PARAM;
00461   }
00462   
00463   /* Allocate MVME_INTERFACE */
00464   *mvme = (MVME_INTERFACE *) calloc(1, sizeof(MVME_INTERFACE));
00465 
00466   (*mvme)->handle = -1;
00467   
00468   /* Allocte VME_TABLE */
00469   (*mvme)->table = (char *) calloc(MAX_VME_SLOTS, sizeof(VME_TABLE));
00470   
00471   /* Set default parameters */
00472   (*mvme)->am = MVME_AM_DEFAULT;
00473 
00474   /* Set default block transfer mode */
00475   (*mvme)->blt_mode = 0; // 0 == disabled
00476 
00477 #if 0
00478   /* create a default master window */
00479   if (vmic_mmap(*mvme, DEFAULT_SRC_ADD, FullWsze((*mvme)->am)) != MVME_SUCCESS) {
00480     printf("mvme_open: cannot create vme map window");
00481     return(MVME_ACCESS_ERROR);
00482   }
00483 #endif
00484 
00485   /* set controls */
00486 
00487   if (1) {
00488      char devname[256];
00489      int fd;
00490      int status;
00491      struct vmeRequesterCfg cfg;
00492 
00493      cfg.requestLevel = 0;      /*  Requester Bus Request Level */
00494      cfg.fairMode = 0;  /*  Requester Fairness Mode Indicator */
00495      cfg.releaseMode = 0;       /*  Requester Bus Release Mode */
00496      cfg.timeonTimeoutTimer = 7;        /*  Master Time-on Time-out Timer */
00497      cfg.timeoffTimeoutTimer = 0;       /*  Master Time-off Time-out Timer */
00498 
00499      sprintf(devname, "%s", "/dev/vme_ctl");
00500      fd = open(devname, O_RDWR);
00501      if (fd < 0) {
00502         fprintf(stderr,"mvme_open: GEFVME VME driver not present? Cannot open VME device \'%s\', errno %d (%s)\n", devname, errno, strerror(errno));
00503         exit(1);
00504      }
00505 
00506      status = ioctl(fd, VME_IOCTL_SET_REQUESTOR, &cfg);
00507      if (status != 0) {
00508         fprintf(stderr,"mvme_open: Cannot set GEFVME VME_IOCTL_SET_REQUESTOR, errno %d (%s)\n", errno, strerror(errno));
00509         exit(1);
00510      }
00511 
00512      close(fd);
00513   }
00514   
00515   return MVME_SUCCESS;
00516 }
00517 
00518 
00519 /********************************************************************/
00520 /**
00521 Close and release ALL the opened VME channel.
00522 @param *mvme     VME structure.
00523 @return MVME_SUCCESS, ERROR
00524 */
00525 int mvme_close(MVME_INTERFACE *mvme)
00526 {
00527   int j;
00528   VME_TABLE *table;
00529   //DMA_INFO  *info;
00530   
00531   table = ((VME_TABLE *)mvme->table);
00532   
00533   /*------------------------------------------------------------*/
00534   /* Close all the window handles */
00535   for (j=0; j< MAX_VME_SLOTS; j++) {
00536     if (table[j].valid) {
00537       close(table[j].handle);
00538     }
00539   } // scan
00540   
00541   /* Free table pointer */
00542   free (mvme->table);
00543   mvme->table = NULL;
00544   
00545   /* Free mvme block */
00546   free (mvme);
00547   
00548   return MVME_SUCCESS;
00549 }
00550 
00551 /********************************************************************/
00552 /**
00553 VME bus reset.
00554 For the VMIC system this will reboot the CPU!
00555 @param *mvme     VME structure.
00556 @return MVME_SUCCESS, ERROR
00557 */
00558 int mvme_sysreset(MVME_INTERFACE *mvme)
00559 {
00560   assert(!"Not implemented");
00561   return MVME_SUCCESS;
00562 }
00563 
00564 int gefvme_read_dma(MVME_INTERFACE *mvme, void *dst, mvme_addr_t vme_addr, int n_bytes)
00565 {
00566   int i;
00567   vmeDmaPacket_t vmeDma;
00568   char* ptr;
00569   int xerrno;
00570   int bytesRead;
00571 
00572   makeDmaPacket(&vmeDma, mvme->blt_mode, mvme->am, vme_addr, dst, n_bytes);
00573   xerrno = runDma(gefvme_dma_channel, &vmeDma);
00574 
00575   if (0)
00576     {
00577       uint32_t *ptr = (uint32_t*)dst;
00578       int i;
00579       printf("dst %p\n", dst);
00580       for (i=0; i<10; i++)
00581         printf("dst[%d] = 0x%08x\n", i, ptr[i]);
00582     }
00583   
00584   if (0)
00585     {
00586       printf("mvme_read_dma: DMA status:\n");
00587       printf("  requested %d bytes\n", n_bytes);
00588       printf("  vmeDmaToken: %d\n", vmeDma.vmeDmaToken);
00589       printf("  vmeDmaWait:  %d\n", vmeDma.vmeDmaWait);
00590       printf("  vmeDmaStartTick: %d\n", vmeDma.vmeDmaStartTick);
00591       printf("  vmeDmaStopTick: %d\n", vmeDma.vmeDmaStopTick);
00592       printf("  vmeDmaElapsedTime: %d\n", vmeDma.vmeDmaElapsedTime);
00593       printf("  vmeDmaStatus: %d\n", vmeDma.vmeDmaStatus);
00594       printf("  byte count: %d\n", vmeDma.byteCount);
00595       //assert(!"Crash here!");
00596     }
00597 
00598   bytesRead = vmeDma.srcAddr - vme_addr;
00599 
00600   //printf("mvme_read_dma: DMA %6d of %6d bytes from 0x%08x, status 0x%08x, byteCount %d, srcAddr 0x%08x, dstAddr 0x%08x\n", n_bytes, bytesRead, vme_addr, vmeDma.vmeDmaStatus, vmeDma.byteCount, vmeDma.srcAddr, vmeDma.dstAddr);
00601   
00602   if (xerrno < 0) {
00603     fprintf(stderr,"gefvme_read_dma: ioctl(VME_IOCTL_START_DMA) errno %d (%s)\n", -xerrno, strerror(-xerrno));
00604     return MVME_ACCESS_ERROR;
00605   }
00606 
00607   if (vmeDma.vmeDmaStatus != 0x02000000) {
00608     //*((uint32_t*)dst) = 0xdeadbeef;
00609     printf("mvme_read_dma: DMA error, read %6d out of %6d bytes from 0x%08x, status 0x%08x, srcAddr 0x%08x, dstAddr 0x%08x\n", bytesRead, n_bytes, vme_addr, vmeDma.vmeDmaStatus, vmeDma.srcAddr, vmeDma.dstAddr);
00610     fprintf(stderr,"mvme_read_dma: ioctl(VME_IOCTL_START_DMA) returned vmeDmaStatus 0x%08x\n", vmeDma.vmeDmaStatus);
00611     return MVME_ACCESS_ERROR;
00612   }
00613   
00614   if (bytesRead!=0 && bytesRead!=n_bytes) {
00615     printf("mvme_read_dma: DMA %6d of %6d bytes from 0x%08x, status 0x%08x, srcAddr 0x%08x, dstAddr 0x%08x\n", n_bytes, bytesRead, vme_addr, vmeDma.vmeDmaStatus, vmeDma.srcAddr, vmeDma.dstAddr);
00616     fprintf(stderr,"mvme_read_dma: ioctl(VME_IOCTL_START_DMA) returned byteCount %d while requested read of %d bytes\n", bytesRead, n_bytes);
00617     return MVME_ACCESS_ERROR;
00618   }
00619 
00620   if (0)
00621     {
00622       int i;
00623       uint32_t *p32 = (uint32_t*)dst;
00624       for (i=0; i<10; i++)
00625         printf("dma at %d is 0x%08x\n", i, p32[i]);
00626     }
00627   
00628   ptr = (char*)dst;
00629   for (i=0; i<n_bytes; i+=4) {
00630     char tmp;
00631     tmp = ptr[i+0];
00632     ptr[i+0] = ptr[i+3];
00633     ptr[i+3] = tmp;
00634     tmp = ptr[i+1];
00635     ptr[i+1] = ptr[i+2];
00636     ptr[i+2] = tmp;
00637   }
00638     
00639   return MVME_SUCCESS;
00640 }
00641 
00642 /********************************************************************/
00643 /**
00644 Read from VME bus. Uses MVME_BLT_BLT32 for enabling the DMA
00645 or size to transfer larger the 128 bytes (32 DWORD)
00646 VME access measurement on a VMIC 7805 is :
00647 Single read access : 1us
00648 DMA    read access : 300ns / DMA latency 28us
00649 @param *mvme VME structure
00650 @param *dst  destination pointer
00651 @param vme_addr source address (VME location).
00652 @param n_bytes requested transfer size.
00653 @return MVME_SUCCESS, ERROR
00654 */
00655 int mvme_read(MVME_INTERFACE *mvme, void *dst, mvme_addr_t vme_addr, mvme_size_t n_bytes)
00656 {
00657   int i, fd;
00658   int offset;
00659   int status;
00660   char* addr;
00661 
00662   /* Perform read */
00663   /*--------------- DMA --------------*/
00664   switch (mvme->blt_mode) {
00665   default:
00666     fprintf(stderr,"mvme_read: Unknown VME block transfer mode %d\n", mvme->blt_mode);
00667     return MVME_ACCESS_ERROR;
00668 
00669   case MVME_AM_A24_SMBLT:
00670   case MVME_AM_A24_NMBLT:
00671   case MVME_AM_A32_SMBLT:
00672   case MVME_AM_A32_NMBLT:
00673   case MVME_BLT_BLT32:
00674   case MVME_BLT_MBLT64:
00675     return gefvme_read_dma(mvme, dst, vme_addr, n_bytes);
00676 
00677   case 0: // no block transfers
00678   
00679     status = gefvme_mapcheck(mvme, vme_addr, n_bytes, &fd, &offset, &addr);
00680     if (status != MVME_SUCCESS)
00681       return status;
00682 
00683     addr += offset;
00684 
00685     if (mvme->dmode == MVME_DMODE_D8) {
00686       char* cdst = (char*)dst;
00687       char* csrc = (char*)addr;
00688       for (i=0; i<n_bytes; i+=sizeof(char))
00689         *cdst++  = *csrc++;
00690     } else if (mvme->dmode == MVME_DMODE_D16) {
00691       WORD* sdst = (WORD*)dst;
00692       WORD* ssrc = (WORD*)addr;
00693       for (i=0; i<n_bytes; i+=sizeof(WORD))
00694         *sdst++  = *ssrc++;
00695     } else if (mvme->dmode == MVME_DMODE_D32) {
00696       DWORD* ddst = (DWORD*)dst;
00697       DWORD* dsrc = (DWORD*)addr;
00698       for (i=0; i<n_bytes; i+=sizeof(DWORD))
00699         *ddst++  = *dsrc++;
00700     } else {
00701       fprintf(stderr,"mvme_read_pio: Invalid dmode %d\n",mvme->dmode);
00702       return MVME_ACCESS_ERROR;
00703     }
00704 
00705 #if 0
00706       for (i=0; i<n_bytes; i+=4) {
00707         char tmp;
00708         tmp = ptr[i+0];
00709         ptr[i+0] = ptr[i+3];
00710         ptr[i+3] = tmp;
00711         tmp = ptr[i+1];
00712         ptr[i+1] = ptr[i+2];
00713         ptr[i+2] = tmp;
00714       }
00715 #endif
00716 
00717 #if 0
00718     status = pread(fd, dst, n_bytes, offset);
00719     if (status != n_bytes)
00720       return MVME_ACCESS_ERROR;
00721 
00722     // NOTE: gefvme PIO block read uses D32 data accesses, so D8 and D16 would not work.
00723     // If gefvme ever implements mmap(), then we can do D8/D16/D32 PIO
00724     // block reads...
00725 
00726     if (mvme->dmode == MVME_DMODE_D8) {
00727       assert(!"mvme_read: VME D8 PIO block read not implemented");
00728     } else if (mvme->dmode == MVME_DMODE_D16) {
00729       assert(!"mvme_read: VME D16 PIO block read not implemented");
00730     } else if (mvme->dmode == MVME_DMODE_D32) {
00731       int i;
00732       char *ptr = (char*)dst;
00733       
00734       for (i=0; i<n_bytes; i+=4) {
00735         char tmp;
00736         tmp = ptr[i+0];
00737         ptr[i+0] = ptr[i+3];
00738         ptr[i+3] = tmp;
00739         tmp = ptr[i+1];
00740         ptr[i+1] = ptr[i+2];
00741         ptr[i+2] = tmp;
00742       }
00743 
00744     } else
00745       assert(!"mvme_read: Unknown value of mvme->dmode. Only MVME_DMODE_D32 and MVME_DMODE_D64 permitted");
00746 #endif
00747 
00748     return MVME_SUCCESS;
00749   }
00750 
00751   assert(!"Cannot be reached!");
00752   return MVME_ACCESS_ERROR;
00753 }
00754 
00755 /********************************************************************/
00756 /**
00757 Read single data from VME bus.
00758 @param *mvme VME structure
00759 @param vme_addr source address (VME location).
00760 @return value return VME data
00761 */
00762 DWORD mvme_read_value(MVME_INTERFACE *mvme, mvme_addr_t vme_addr)
00763 {
00764   int status, fd, offset;
00765   char *addr;
00766   DWORD dst = 0;
00767   unsigned char tmp[4];
00768   
00769   status = gefvme_mapcheck(mvme, vme_addr, 4, &fd, &offset, &addr);
00770   if (status != MVME_SUCCESS)
00771     return 0xFFFFFFFF;
00772   
00773   //printf("mvme_read_value: fd %d, vmeaddr 0x%08x, offset %d, addr %p\n", fd, vme_addr, offset, addr);
00774 
00775   addr += offset;
00776   
00777   /* Perform read */
00778   if (mvme->dmode == MVME_DMODE_D8)
00779     dst  = *((char *)addr);
00780   else if (mvme->dmode == MVME_DMODE_D16) {
00781     *((WORD*)tmp) = *((WORD*)addr);
00782     dst = tmp[0]<<8 | tmp[1];
00783   }
00784   else if (mvme->dmode == MVME_DMODE_D32) {
00785     *((DWORD*)tmp) = *((DWORD*)addr);
00786     dst = tmp[0]<<24 | tmp[1]<<16 | tmp[2]<<8 | tmp[3];
00787   }
00788 
00789 #if 0  
00790   /* Perform read */
00791   if (mvme->dmode == MVME_DMODE_D8) {
00792     status = pread(fd, &dst, 1, offset);
00793     if (status != 1) {
00794       //fprintf(stderr,"mvme_read_value: read() returned %d, errno %d (%s)\n", status, errno, strerror(errno));
00795       return 0xFF;
00796     }
00797   } else if (mvme->dmode == MVME_DMODE_D16) {
00798     char buf16[2];
00799     uint16_t dst16;
00800     status = pread(fd, buf16, 2, offset);
00801     dst16 = (buf16[1]&0xFF) | (buf16[0]<<8);
00802     //printf("read16: addr 0x%x, value 0x%02x 0x02x 0x%04x, status %d\n", vme_addr, buf16[0], buf16[1], dst16, status);
00803     if (status == 2)
00804       return dst16;
00805 
00806     //fprintf(stderr,"mvme_read_value: read() returned %d, errno %d (%s)\n", status, errno, strerror(errno));
00807     return 0xFFFF;
00808   } else if (mvme->dmode == MVME_DMODE_D32) {
00809     char buf32[4];
00810     uint32_t dst32;
00811     status = pread(fd, buf32, 4, offset);
00812     dst32 = (buf32[3]&0xFF) | (0xFF00&buf32[2]<<8)| (0xFF0000&buf32[1]<<16) | (0xFF000000&buf32[0]<<24);
00813     //printf("read32: fd %d, addr 0x%x, offset 0x%x, value 0x%02x 0x%02x 0x%02x 0x%02x 0x%08x, status %d\n", fd, vme_addr, offset, buf32[0], buf32[1], buf32[2], buf32[3], dst32, status);
00814     //exit(1);
00815     if (status == 4)
00816       return dst32;
00817 
00818     //fprintf(stderr,"mvme_read_value: read() returned %d, errno %d (%s)\n", status, errno, strerror(errno));
00819     return 0xFFFFFFFF;
00820   }
00821 #endif
00822 
00823   return dst;
00824 }
00825 
00826 /********************************************************************/
00827 /**
00828 Write data to VME bus. Uses MVME_BLT_BLT32 for enabling the DMA
00829 or size to transfer larger the 128 bytes (32 DWORD)
00830 @param *mvme VME structure
00831 @param vme_addr source address (VME location).
00832 @param *src source array
00833 @param n_bytes  size of the array in bytes
00834 @return MVME_SUCCESS, MVME_ACCESS_ERROR
00835 */
00836 int mvme_write(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, void *src, mvme_size_t n_bytes)
00837 {
00838   assert(!"Not implemented");
00839 #if 0
00840   /* Perform write */
00841   /*--------------- DMA --------------*/
00842   if ((mvme->blt_mode == MVME_BLT_BLT32) ||
00843       (mvme->blt_mode == MVME_BLT_MBLT64) ||
00844       (n_bytes > 127)) {
00845 
00846     DMA_INFO  *info = ((DMA_INFO  *)mvme->info);
00847 
00848     if (n_bytes >= DEFAULT_DMA_NBYTES)
00849       {
00850         fprintf(stderr,"mvme_write: Attempt to DMA %d bytes more than DEFAULT_DMA_NBYTES=%d\n", (int)n_bytes, DEFAULT_DMA_NBYTES);
00851         return(ERROR);
00852       }
00853 
00854     memcpy(info->dma_ptr, src, n_bytes);
00855     
00856     if(0 > vme_dma_write((vme_bus_handle_t )mvme->handle
00857        , info->dma_handle
00858        , 0
00859        , vme_addr
00860        , mvme->am
00861        , n_bytes
00862        , 0)) {
00863       perror("Error writing data");
00864       return(MVME_ACCESS_ERROR);
00865     }
00866   } else {
00867     int i;
00868     mvme_addr_t addr;
00869   
00870     /*--------------- Single Access -------------*/
00871     addr = vmic_mapcheck(mvme, vme_addr, n_bytes);
00872     
00873     /* Perform write */
00874     if (mvme->dmode == MVME_DMODE_D8) {
00875       char*dst = (char*)addr;
00876       char*sss = (char*)src;
00877       for (i=0; i<n_bytes; i+=sizeof(char))
00878         *dst++ = *sss++;
00879     } else if (mvme->dmode == MVME_DMODE_D16) {
00880       WORD*dst = (WORD*)addr;
00881       WORD*sss = (WORD*)src;
00882       for (i=0; i<n_bytes; i+=sizeof(WORD))
00883         *dst++ = *sss++;
00884     } else if (mvme->dmode == MVME_DMODE_D32) {
00885       DWORD*dst = (DWORD*)addr;
00886       DWORD*sss = (DWORD*)src;
00887       for (i=0; i<n_bytes; i+=sizeof(DWORD))
00888         *dst++ = *sss++;
00889     } else {
00890       fprintf(stderr,"mvme_write: Invalid dmode %d\n",mvme->dmode);
00891       return(ERROR);
00892     }
00893   }
00894   return MVME_SUCCESS;
00895 #endif
00896 }
00897 
00898 /********************************************************************/
00899 /**
00900 Write single data to VME bus.
00901 @param *mvme VME structure
00902 @param vme_addr destination address (VME location).
00903 @param value  data to write to the VME address.
00904 @return MVME_SUCCESS
00905 */
00906 int mvme_write_value(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, DWORD value)
00907 {
00908   int status, fd, offset;
00909   char* addr;
00910   
00911   status = gefvme_mapcheck(mvme, vme_addr, 4, &fd, &offset, &addr);
00912   if (status != MVME_SUCCESS)
00913     return status;
00914 
00915 #if 1
00916   addr += offset;
00917   
00918   /* Perform write */
00919   if (mvme->dmode == MVME_DMODE_D8)
00920     *((char *)addr)  = (char) (value &  0xFF);
00921   else if (mvme->dmode == MVME_DMODE_D16) {
00922     unsigned char buf[2];
00923     buf[1] = value & 0xFF;
00924     buf[0] = value >> 8;
00925     *((WORD *)addr)  = *(WORD*) buf;
00926   }
00927   else if (mvme->dmode == MVME_DMODE_D32) {
00928     unsigned char buf[4];
00929     buf[3] = value;
00930     buf[2] = value >> 8;
00931     buf[1] = value >> 16;
00932     buf[0] = value >> 24;
00933     *((DWORD *)addr)  = *(DWORD*) buf;
00934   }
00935 #else
00936   /* Perform read */
00937   if (mvme->dmode == MVME_DMODE_D8) {
00938     status = pwrite(fd, &value, 1, offset);
00939   } else if (mvme->dmode == MVME_DMODE_D16) {
00940     char buf[2];
00941     buf[0] = (value&0xff00) >> 8;
00942     buf[1] = (value&0xff);
00943     status = pwrite(fd, buf, 2, offset);
00944   } else if (mvme->dmode == MVME_DMODE_D32) {
00945     char buf[4];
00946     buf[0] = (value&0xff000000) >> 24;
00947     buf[1] = (value&0xff0000) >> 16;
00948     buf[2] = (value&0xff00) >> 8;
00949     buf[3] = (value&0xff);
00950     status = pwrite(fd, buf, 4, offset);
00951   }
00952 #endif
00953 
00954   return MVME_SUCCESS;
00955 }
00956 
00957 /********************************************************************/
00958 int mvme_set_am(MVME_INTERFACE *mvme, int am)
00959 {
00960   mvme->am = am;
00961   return MVME_SUCCESS;
00962 }
00963 
00964 /********************************************************************/
00965 int EXPRT mvme_get_am(MVME_INTERFACE *mvme, int *am)
00966 {
00967   *am = mvme->am;
00968   return MVME_SUCCESS;
00969 }
00970 
00971 /********************************************************************/
00972 int mvme_set_dmode(MVME_INTERFACE *mvme, int dmode)
00973 {
00974   mvme->dmode = dmode;
00975   return MVME_SUCCESS;
00976 }
00977 
00978 /********************************************************************/
00979 int mvme_get_dmode(MVME_INTERFACE *mvme, int *dmode)
00980 {
00981   *dmode = mvme->dmode;
00982   return MVME_SUCCESS;
00983 }
00984 
00985 /********************************************************************/
00986 int mvme_set_blt(MVME_INTERFACE *mvme, int mode)
00987 {
00988   mvme->blt_mode = mode;
00989   return MVME_SUCCESS;
00990 }
00991 
00992 /********************************************************************/
00993 int mvme_get_blt(MVME_INTERFACE *mvme, int *mode)
00994 {
00995   *mode = mvme->blt_mode;
00996   return MVME_SUCCESS;
00997 }
00998 
00999 /********************************************************************/
01000 int mvme_interrupt_generate(MVME_INTERFACE *mvme, int level, int vector, void *info)
01001 {
01002   assert(!"Not implemented");
01003   return MVME_SUCCESS;
01004 }
01005 
01006 /********************************************************************/
01007 /**
01008 
01009 <code>
01010 static void handler(int sig, siginfo_t * siginfo, void *extra)
01011 {
01012         print_intr_msg(level, siginfo->si_value.sival_int);
01013         done = 0;
01014 }
01015 </endcode>
01016 
01017 */
01018 int mvme_interrupt_attach(MVME_INTERFACE *mvme, int level, int vector
01019                                         , void (*isr)(int, void*, void *), void *info)
01020 {
01021   assert(!"Not implemented");
01022   return MVME_SUCCESS;
01023 }
01024 
01025 /********************************************************************/
01026 int mvme_interrupt_detach(MVME_INTERFACE *mvme, int level, int vector, void *info)
01027 {
01028   assert(!"Not implemented");
01029   return MVME_SUCCESS;
01030 }
01031 
01032 /********************************************************************/
01033 int mvme_interrupt_enable(MVME_INTERFACE *mvme, int level, int vector, void *info)
01034 {
01035   assert(!"Not implemented");
01036   return MVME_SUCCESS;
01037 }
01038 
01039 /********************************************************************/
01040 int mvme_interrupt_disable(MVME_INTERFACE *mvme, int level, int vector, void *info)
01041 {
01042   assert(!"Not implemented");
01043   return MVME_SUCCESS;
01044 }
01045 
01046 //end

Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk