vmicvme.c

Go to the documentation of this file.
00001 /*********************************************************************
00002 Name:         vmicvme.c
00003 Created by:   Pierre-Andre Amaudruz
00004 
00005 Contents:     VME interface for the VMIC VME board processor
00006               using the mvmestd VME call convention.
00007 
00008 $Id$
00009 
00010 *********************************************************************/
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <stdlib.h>
00014 #include <signal.h>
00015 #include <unistd.h>
00016 #include <assert.h>
00017 #include <errno.h>
00018 
00019 #include "vmicvme.h"
00020 
00021 vme_bus_handle_t bus_handle;
00022 vme_interrupt_handle_t int_handle;
00023 
00024 struct sigevent event;
00025 struct sigaction handler_act;
00026 
00027 INT_INFO int_info;
00028 
00029 int vmicvme_max_dma_nbytes = DEFAULT_DMA_NBYTES;
00030 
00031 mvme_size_t FullWsze (int am);
00032 int vmic_mmap(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t size);
00033 int vmic_unmap(MVME_INTERFACE *mvme, mvme_addr_t vmE_addr, mvme_size_t size);
00034 mvme_addr_t vmic_mapcheck (MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t n_bytes);
00035 
00036 #define A32_CHUNK 0x00FFFFFF
00037 
00038 /********************************************************************/
00039 /**
00040 Return the largest window size based on the address modifier.
00041 For A32, VMIC cannot map a full 32bit address space.
00042 We map it in chunks of 16 Mbytes instead
00043 */
00044 mvme_size_t FullWsze (int am) {
00045   switch (am & 0xF0) {
00046   case 0x00:
00047     return A32_CHUNK; // map A32 space in chunks of 16Mibytes
00048   case 0x30:
00049     return 0xFFFFFF; // map all of the A24 address space: 16Mibytes
00050   case 0x20:
00051     return 0xFFFF; // map all of the A16 address space: 64kibytes
00052   default:
00053     return 0;
00054   }
00055 }
00056 
00057 /********************************************************************/
00058 /**
00059 Open a VME channel
00060 One bus handle per crate.
00061 @param *mvme     VME structure.
00062 @param index    VME interface index
00063 @return MVME_SUCCESS, ERROR
00064 */
00065 int mvme_open(MVME_INTERFACE **mvme, int index)
00066 {
00067   DMA_INFO *info;
00068   
00069   /* index can be only 0 for VMIC */
00070   if (index != 0) {
00071     perror("Invalid parameter (index != 0");
00072     (*mvme)->handle = 0;
00073     return(MVME_INVALID_PARAM);
00074   }
00075   
00076   /* Allocate MVME_INTERFACE */
00077   *mvme = (MVME_INTERFACE *) calloc(1, sizeof(MVME_INTERFACE));
00078   
00079   /* Going through init once only */
00080   if(0 > vme_init( (vme_bus_handle_t *) &((*mvme)->handle))) {
00081     perror("Error initializing the VMIC VMEbus");
00082     (*mvme)->handle = 0;
00083     return(MVME_NO_INTERFACE);
00084   }
00085   
00086   /* Allocte VME_TABLE */
00087   (*mvme)->table = (char *) calloc(MAX_VME_SLOTS, sizeof(VME_TABLE));
00088   
00089   /* Set default parameters */
00090   (*mvme)->am = MVME_AM_DEFAULT;
00091 
00092   /* create a default master window */
00093   if (vmic_mmap(*mvme, DEFAULT_SRC_ADD, FullWsze((*mvme)->am)) != MVME_SUCCESS) {
00094     printf("mvme_open: cannot create vme map window");
00095     return(MVME_ACCESS_ERROR);
00096   }
00097   
00098   /* Allocate DMA_INFO */
00099   info = (DMA_INFO *) calloc(1, sizeof(DMA_INFO));
00100   
00101   (*mvme)->info = info;
00102 
00103   while (1) {
00104 
00105     /* Create DMA buffer */
00106     int status = vme_dma_buffer_create( (vme_bus_handle_t) (*mvme)->handle
00107                                         , &(info->dma_handle)
00108                                         , vmicvme_max_dma_nbytes, 0, NULL);
00109     if (status >= 0)
00110       break;
00111 
00112     fprintf(stderr,"mvme_open: Cannot create VME DMA buffer of size %d, errno %d (%s)\n", vmicvme_max_dma_nbytes, errno, strerror(errno));
00113     vmicvme_max_dma_nbytes /= 2;
00114 
00115     if (vmicvme_max_dma_nbytes >= 1024) {
00116       fprintf(stderr,"mvme_open: Allocated VME DMA buffer of size %d\n", vmicvme_max_dma_nbytes);
00117       continue;
00118     }
00119 
00120     assert(!"Cannot allocate VME DMA buffer!");
00121   }
00122   
00123   if(NULL == (info->dma_ptr = vme_dma_buffer_map(
00124              (vme_bus_handle_t) (*mvme)->handle
00125              , info->dma_handle
00126              , 0)))
00127     {
00128       perror("mvme_open: Error mapping the DMA buffer");
00129       vme_dma_buffer_release((vme_bus_handle_t) (*mvme)->handle, info->dma_handle);
00130       assert(!"Cannot map the DMA buffer!");
00131       return(ERROR);
00132     }
00133 
00134   printf("mvme_open:\n");
00135   printf("Bus handle              = 0x%x\n", (*mvme)->handle);
00136   printf("DMA handle              = 0x%x\n", (int)info->dma_handle);
00137   printf("DMA area size           = %d bytes\n", vmicvme_max_dma_nbytes);
00138   printf("DMA    physical address = %p\n", (unsigned long *) info->dma_ptr);
00139   
00140   return(MVME_SUCCESS);
00141 }
00142 
00143 
00144 /********************************************************************/
00145 /**
00146 Close and release ALL the opened VME channel.
00147 @param *mvme     VME structure.
00148 @return MVME_SUCCESS, ERROR
00149 */
00150 int mvme_close(MVME_INTERFACE *mvme)
00151 {
00152   int j;
00153   VME_TABLE *table;
00154   DMA_INFO  *info;
00155   
00156   table = ((VME_TABLE *)mvme->table);
00157   info  = ((DMA_INFO  *)mvme->info);
00158   
00159   // Debug
00160   printf("mvme_close:\n");
00161   printf("Bus handle              = 0x%x\n", mvme->handle);
00162   printf("DMA handle              = 0x%x\n", (int)info->dma_handle);
00163   printf("DMA    physical address = %p\n", (unsigned long *) info->dma_ptr);
00164   
00165   /*------------------------------------------------------------*/
00166   /* Close DMA channel */
00167   /*-PAA- The code below generate a crash on the VMIC7805 running
00168     Linux 2.6.12.3. Seems to be traced to a wrong link list handling
00169     in vme_dma.c module.
00170     Running without deallocation seems not to cause problem for now.
00171     Will investigate further.
00172     status = vme_dma_buffer_unmap((vme_bus_handle_t ) mvme->handle, info->dma_handle);
00173     if (status > 0) {
00174     perror("Error unmapping the buffer");
00175     }
00176     
00177     status = vme_dma_buffer_release((vme_bus_handle_t ) mvme->handle, info->dma_handle);
00178     if (status > 0) {
00179     perror("Error releasing the buffer");
00180     }
00181   */
00182   
00183   /* Free info (DMA) allocation */
00184   free (mvme->info);
00185   
00186   /*------------------------------------------------------------*/
00187   /* Close all the window handles */
00188   for (j=0; j< MAX_VME_SLOTS; j++) {
00189     if (table[j].valid) {
00190       vme_master_window_release( (vme_bus_handle_t ) mvme->handle
00191          , table[j].wh );
00192     }
00193   } // scan
00194   
00195   /* Free table pointer */
00196   free (mvme->table);
00197   mvme->table = NULL;
00198   
00199   /* close the bus handle */
00200   if (mvme->handle != 0) {
00201     if (0 > vme_term( (vme_bus_handle_t) mvme->handle)) {
00202       perror("Error during VME termination");
00203       return(MVME_ACCESS_ERROR);
00204     }
00205   }
00206   
00207   /* Free mvme block */
00208   free (mvme);
00209   
00210   return(MVME_SUCCESS);
00211 }
00212 
00213 /********************************************************************/
00214 /**
00215 VME bus reset.
00216 For the VMIC system this will reboot the CPU!
00217 @param *mvme     VME structure.
00218 @return MVME_SUCCESS, ERROR
00219 */
00220 int mvme_sysreset(MVME_INTERFACE *mvme)
00221 {
00222   if (vme_sysreset((vme_bus_handle_t )mvme->handle)) {
00223     perror("vmeSysreset");
00224     return  MVME_ACCESS_ERROR;
00225   }
00226   return MVME_SUCCESS;
00227 }
00228 
00229 /********************************************************************/
00230 /**
00231 Read from VME bus. Uses MVME_BLT_BLT32 for enabling the DMA
00232 or size to transfer larger the 128 bytes (32 DWORD)
00233 VME access measurement on a VMIC 7805 is :
00234 Single read access : 1us
00235 DMA    read access : 300ns / DMA latency 28us
00236 @param *mvme VME structure
00237 @param *dst  destination pointer
00238 @param vme_addr source address (VME location).
00239 @param n_bytes requested transfer size.
00240 @return MVME_SUCCESS, ERROR
00241 */
00242 int mvme_read(MVME_INTERFACE *mvme, void *dst, mvme_addr_t vme_addr, mvme_size_t n_bytes)
00243 {
00244   int         status;
00245 
00246   /* Perform read */
00247   /*--------------- DMA --------------*/
00248   if ((mvme->blt_mode == MVME_BLT_BLT32) ||
00249       (mvme->blt_mode == MVME_BLT_MBLT64) ||
00250       (n_bytes > 127)) {
00251 
00252     int am = mvme->am;
00253 
00254 #ifdef DO_TIMING
00255     struct timeval t1, t2, t3;
00256     int dt1, dt2;
00257 #endif
00258 
00259     DMA_INFO *info = ((DMA_INFO*)mvme->info);
00260 
00261     if (n_bytes >= vmicvme_max_dma_nbytes)
00262       {
00263         fprintf(stderr,"mvme_read: Attempt to DMA %d bytes more than DEFAULT_DMA_NBYTES=%d\n", (int)n_bytes, vmicvme_max_dma_nbytes);
00264         return(ERROR);
00265       }
00266 
00267     if (mvme->blt_mode == MVME_BLT_BLT32)
00268       am = MVME_AM_A24_NB;
00269     else if (mvme->blt_mode == MVME_BLT_MBLT64)
00270       am = MVME_AM_A24_NMBLT;
00271 
00272 #ifdef DO_TIMING
00273     gettimeofday(&t1,NULL);
00274 #endif
00275 
00276     status = vme_dma_read((vme_bus_handle_t )mvme->handle
00277         , info->dma_handle
00278         , 0
00279         , vme_addr
00280         , am
00281         , n_bytes
00282         , 0);
00283     if (status != 0) {
00284       fprintf(stderr,"mvme_read: dma read: addr 0x%x, am 0x%x, bytes: %d, status: %d\n", vme_addr, mvme->am, n_bytes, status);
00285       perror("mvme_read: Error in vme_dma_read()");
00286       return(ERROR);
00287     }
00288 
00289 #ifdef DO_TIMING
00290     gettimeofday(&t2,NULL);
00291 #endif
00292 
00293     memcpy(dst,info->dma_ptr,n_bytes);
00294 
00295 #ifdef DO_TIMING
00296     gettimeofday(&t3,NULL);
00297 
00298     dt1 = t2.tv_usec - t1.tv_usec;
00299     dt2 = t3.tv_usec - t2.tv_usec;
00300 
00301     //fprintf(stderr,"dma read: addr 0x%x, am 0x%x, bytes: %d, status: %d, dma time: %d, memcpy time: %d, dma rate: %f, effective rate: %f\n", vme_addr, mvme->am, n_bytes, status, dt1, dt2, (double)n_bytes/(double)dt1,(double)n_bytes/(double)(dt1+dt2));
00302 #endif
00303   } else {
00304     int i;
00305     mvme_addr_t addr;
00306 
00307     /*--------------- Single Access -------------*/
00308     addr = vmic_mapcheck(mvme, vme_addr, n_bytes);
00309     
00310     if (mvme->dmode == MVME_DMODE_D8) {
00311       char* cdst = (char*)dst;
00312       char* csrc = (char*)addr;
00313       for (i=0; i<n_bytes; i+=sizeof(char))
00314         *cdst++  = *csrc++;
00315     } else if (mvme->dmode == MVME_DMODE_D16) {
00316       WORD* sdst = (WORD*)dst;
00317       WORD* ssrc = (WORD*)addr;
00318       for (i=0; i<n_bytes; i+=sizeof(WORD))
00319         *sdst++  = *ssrc++;
00320     } else if (mvme->dmode == MVME_DMODE_D32) {
00321       DWORD* ddst = (DWORD*)dst;
00322       DWORD* dsrc = (DWORD*)addr;
00323       for (i=0; i<n_bytes; i+=sizeof(DWORD))
00324         *ddst++  = *dsrc++;
00325     } else {
00326       fprintf(stderr,"mvme_read: Invalid dmode %d\n",mvme->dmode);
00327       return(ERROR);
00328     }
00329   }
00330   
00331   return(MVME_SUCCESS);
00332 }
00333 
00334 /********************************************************************/
00335 /**
00336 Read single data from VME bus.
00337 @param *mvme VME structure
00338 @param vme_addr source address (VME location).
00339 @return value return VME data
00340 */
00341 DWORD mvme_read_value(MVME_INTERFACE *mvme, mvme_addr_t vme_addr)
00342 {
00343   mvme_addr_t addr;
00344   DWORD dst = 0xFFFFFFFF;
00345   
00346   addr = vmic_mapcheck(mvme, vme_addr, 4);
00347   
00348   /* Perform read */
00349   if (mvme->dmode == MVME_DMODE_D8)
00350     dst  = *((char *)addr);
00351   else if (mvme->dmode == MVME_DMODE_D16)
00352     dst  = *((WORD *)addr);
00353   else if (mvme->dmode == MVME_DMODE_D32)
00354     dst = *((DWORD *)addr);
00355   
00356   return(dst);
00357 }
00358 
00359 /********************************************************************/
00360 /**
00361 Write data to VME bus. Uses MVME_BLT_BLT32 for enabling the DMA
00362 or size to transfer larger the 128 bytes (32 DWORD)
00363 @param *mvme VME structure
00364 @param vme_addr source address (VME location).
00365 @param *src source array
00366 @param n_bytes  size of the array in bytes
00367 @return MVME_SUCCESS, MVME_ACCESS_ERROR
00368 */
00369 int mvme_write(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, void *src, mvme_size_t n_bytes)
00370 {
00371   /* Perform write */
00372   /*--------------- DMA --------------*/
00373   if ((mvme->blt_mode == MVME_BLT_BLT32) ||
00374       (mvme->blt_mode == MVME_BLT_MBLT64) ||
00375       (n_bytes > 127)) {
00376 
00377     DMA_INFO  *info = ((DMA_INFO  *)mvme->info);
00378 
00379     if (n_bytes >= vmicvme_max_dma_nbytes)
00380       {
00381         fprintf(stderr,"mvme_write: Attempt to DMA %d bytes more than DEFAULT_DMA_NBYTES=%d\n", (int)n_bytes, vmicvme_max_dma_nbytes);
00382         return(ERROR);
00383       }
00384 
00385     memcpy(info->dma_ptr, src, n_bytes);
00386     
00387     if(0 > vme_dma_write((vme_bus_handle_t )mvme->handle
00388        , info->dma_handle
00389        , 0
00390        , vme_addr
00391        , mvme->am
00392        , n_bytes
00393        , 0)) {
00394       perror("Error writing data");
00395       return(MVME_ACCESS_ERROR);
00396     }
00397   } else {
00398     int i;
00399     mvme_addr_t addr;
00400   
00401     /*--------------- Single Access -------------*/
00402     addr = vmic_mapcheck(mvme, vme_addr, n_bytes);
00403     
00404     /* Perform write */
00405     if (mvme->dmode == MVME_DMODE_D8) {
00406       char*dst = (char*)addr;
00407       char*sss = (char*)src;
00408       for (i=0; i<n_bytes; i+=sizeof(char))
00409         *dst++ = *sss++;
00410     } else if (mvme->dmode == MVME_DMODE_D16) {
00411       WORD*dst = (WORD*)addr;
00412       WORD*sss = (WORD*)src;
00413       for (i=0; i<n_bytes; i+=sizeof(WORD))
00414         *dst++ = *sss++;
00415     } else if (mvme->dmode == MVME_DMODE_D32) {
00416       DWORD*dst = (DWORD*)addr;
00417       DWORD*sss = (DWORD*)src;
00418       for (i=0; i<n_bytes; i+=sizeof(DWORD))
00419         *dst++ = *sss++;
00420     } else {
00421       fprintf(stderr,"mvme_write: Invalid dmode %d\n",mvme->dmode);
00422       return(ERROR);
00423     }
00424   }
00425   return MVME_SUCCESS;
00426 }
00427 
00428 /********************************************************************/
00429 /**
00430 Write single data to VME bus.
00431 @param *mvme VME structure
00432 @param vme_addr destination address (VME location).
00433 @param value  data to write to the VME address.
00434 @return MVME_SUCCESS
00435 */
00436 int mvme_write_value(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, DWORD value)
00437 {
00438   mvme_addr_t addr;
00439   
00440   addr = vmic_mapcheck(mvme, vme_addr, 4);
00441   
00442   /* Perform write */
00443   if (mvme->dmode == MVME_DMODE_D8)
00444     *((char *)addr)  = (char) (value &  0xFF);
00445   else if (mvme->dmode == MVME_DMODE_D16)
00446     *((WORD *)addr)  = (WORD) (value &  0xFFFF);
00447   else if (mvme->dmode == MVME_DMODE_D32)
00448     *((DWORD *)addr)  = value;
00449   
00450   return MVME_SUCCESS;
00451 }
00452 
00453 /********************************************************************/
00454 int mvme_set_am(MVME_INTERFACE *mvme, int am)
00455 {
00456   mvme->am = am;
00457   return MVME_SUCCESS;
00458 }
00459 
00460 /********************************************************************/
00461 int EXPRT mvme_get_am(MVME_INTERFACE *mvme, int *am)
00462 {
00463   *am = mvme->am;
00464   return MVME_SUCCESS;
00465 }
00466 
00467 /********************************************************************/
00468 int mvme_set_dmode(MVME_INTERFACE *mvme, int dmode)
00469 {
00470   mvme->dmode = dmode;
00471   return MVME_SUCCESS;
00472 }
00473 
00474 /********************************************************************/
00475 int mvme_get_dmode(MVME_INTERFACE *mvme, int *dmode)
00476 {
00477   *dmode = mvme->dmode;
00478   return MVME_SUCCESS;
00479 }
00480 
00481 /********************************************************************/
00482 int mvme_set_blt(MVME_INTERFACE *mvme, int mode)
00483 {
00484   mvme->blt_mode = mode;
00485   return MVME_SUCCESS;
00486 }
00487 
00488 /********************************************************************/
00489 int mvme_get_blt(MVME_INTERFACE *mvme, int *mode)
00490 {
00491   *mode = mvme->blt_mode;
00492   return MVME_SUCCESS;
00493 }
00494 
00495 /********************************************************************/
00496 /*
00497 static void myisr(int sig, siginfo_t * siginfo, void *extra)
00498 {
00499   fprintf(stderr, "myisr interrupt received \n");
00500   fprintf(stderr, "interrupt: level:%d Vector:0x%x\n", int_info.level, siginfo->si_value.sival_int & 0xFF);
00501 }
00502 */
00503 /********************************************************************/
00504 int mvme_interrupt_generate(MVME_INTERFACE *mvme, int level, int vector, void *info)
00505 {
00506   if (vme_interrupt_generate((vme_bus_handle_t )mvme->handle, level, vector)) {
00507     perror("vme_interrupt_generate");
00508     return MVME_ERROR;
00509   }
00510 
00511   return MVME_SUCCESS;
00512 }
00513 
00514 /********************************************************************/
00515 /**
00516 
00517 <code>
00518 static void handler(int sig, siginfo_t * siginfo, void *extra)
00519 {
00520         print_intr_msg(level, siginfo->si_value.sival_int);
00521         done = 0;
00522 }
00523 </endcode>
00524 
00525 */
00526 int mvme_interrupt_attach(MVME_INTERFACE *mvme, int level, int vector
00527                                         , void (*isr)(int, void*, void *), void *info)
00528 {
00529         struct sigevent event;
00530         struct sigaction handler_act;
00531 
00532         /* Set up sigevent struct */
00533         event.sigev_signo = SIGIO;
00534         event.sigev_notify = SIGEV_SIGNAL;
00535         event.sigev_value.sival_int = 0;
00536 
00537         /* Install the signal handler */
00538         sigemptyset(&handler_act.sa_mask);
00539         handler_act.sa_sigaction = (void*)isr;
00540         handler_act.sa_flags = SA_SIGINFO;
00541 
00542         if (sigaction(SIGIO, &handler_act, NULL)) {
00543                 perror("sigaction");
00544                 return -1;
00545         }
00546 
00547         int_info.flags = *((unsigned int *) info);
00548 
00549   if (vme_interrupt_attach((vme_bus_handle_t )mvme->handle
00550                       , &int_handle, level, vector
00551                       , int_info.flags, &event)) {
00552     perror("vme_interrupt_attach");
00553     return -1;
00554   }
00555   int_info.handle = int_handle;
00556   int_info.level  = level;
00557   int_info.vector = vector;
00558 
00559   return MVME_SUCCESS;
00560 }
00561 
00562 /********************************************************************/
00563 int mvme_interrupt_detach(MVME_INTERFACE *mvme, int level, int vector, void *info)
00564 {
00565   if (int_info.handle) {
00566     
00567     if (vme_interrupt_release((vme_bus_handle_t )mvme->handle
00568                               , int_info.handle)) {
00569       perror("vme_interrupt_release");
00570       return -1;
00571     }
00572   }
00573   return MVME_SUCCESS;
00574 }
00575 
00576 /********************************************************************/
00577 int mvme_interrupt_enable(MVME_INTERFACE *mvme, int level, int vector, void *info)
00578 {
00579   //  vme_interrupt_enable((vme_bus_handle_t )mvme->handle,
00580   //                   int_info.handle);
00581   return MVME_SUCCESS;
00582 }
00583 
00584 /********************************************************************/
00585 int mvme_interrupt_disable(MVME_INTERFACE *mvme, int level, int vector, void *info)
00586 {
00587   return MVME_SUCCESS;
00588 }
00589 
00590 /********************************************************************/
00591 /**
00592 VME Memory map, uses the driver MVME_INTERFACE for storing the map information.
00593 @param *mvme VME structure
00594 @param vme_addr source address (VME location).
00595 @param n_bytes  data to write
00596 @return MVME_SUCCESS, MVME_ACCESS_ERROR
00597 */
00598 int vmic_mmap(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t n_bytes)
00599 {
00600   int j;
00601   void *phys_addr = NULL;
00602   VME_TABLE *table;
00603   
00604   table = (VME_TABLE *) mvme->table;
00605   
00606   /* Find new slot */
00607   j=0;
00608   while (table[j].valid)  j++;
00609   
00610   if (j < MAX_VME_SLOTS) {
00611     /* Create a new window */
00612     table[j].low    = vme_addr;
00613     table[j].am     = ((mvme->am == 0) ? MVME_AM_DEFAULT : mvme->am);
00614     table[j].nbytes = n_bytes;
00615     
00616     /* Create master window */
00617     if(0 > vme_master_window_create( (vme_bus_handle_t )mvme->handle
00618              , &(table[j].wh)
00619              , table[j].low
00620              , table[j].am
00621              , table[j].nbytes
00622              , VME_CTL_PWEN
00623              , NULL) ) {
00624       perror("Error creating the window");
00625       return(MVME_ACCESS_ERROR);
00626     }
00627     
00628     /* Create the mapped window */
00629     if(NULL == (table[j].ptr = (DWORD *)vme_master_window_map((vme_bus_handle_t )mvme->handle, table[j].wh, 0) ) ) {
00630       perror("Error mapping the window");
00631       vme_master_window_release( (vme_bus_handle_t )mvme->handle
00632          , table[j].wh );
00633       
00634       /* Cleanup slot */
00635       table[j].wh = 0;
00636       return(MVME_ACCESS_ERROR);
00637     }
00638     
00639     if (NULL == (phys_addr = vme_master_window_phys_addr ((vme_bus_handle_t )mvme->handle, table[j].wh)))
00640       {
00641         perror ("vme_master_window_phys_addr");
00642       }
00643     fprintf(stderr, "vmic_mmap: Mapped VME AM 0x%02x addr 0x%08x size 0x%08x at address %p\n", table[j].am, (int)vme_addr, (int)n_bytes, phys_addr);
00644     table[j].valid = 1;
00645     table[j].high  = (table[j].low + table[j].nbytes);
00646   }
00647   else {
00648     /* No more slot available */
00649     return(MVME_ACCESS_ERROR);
00650   }
00651   
00652   return(MVME_SUCCESS);
00653 }
00654 
00655 /********************************************************************/
00656 /**
00657 Unmap VME region.
00658 VME Memory map, uses the driver MVME_INTERFACE for storing the map information.
00659 @param *mvme VME structure
00660 @param  nbytes requested transfer size.
00661 @return MVME_SUCCESS, ERROR
00662 */
00663 int vmic_unmap(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t size)
00664 {
00665   int j;
00666   VME_TABLE *table;
00667   table = (VME_TABLE *) mvme->table;
00668   /* Search for map window */
00669   for (j=0; table[j].valid; j++) {
00670     /* Check the vme address range */
00671     if ((vme_addr == table[j].low) && ((vme_addr+size) == table[j].high)) {
00672       /* window found */
00673       break;
00674     }
00675   }
00676   if (!table[j].valid) {
00677     /* address not found => nothing to do */
00678     return(MVME_SUCCESS);
00679   }
00680   /* Remove map */
00681   if (table[j].ptr) {
00682     if (0 > vme_master_window_unmap ((vme_bus_handle_t )mvme->handle, table[j].wh)) {
00683       perror ("vme_master_window_unmap");
00684       return(ERROR);
00685     }
00686     if (0 > vme_master_window_release ((vme_bus_handle_t )mvme->handle, table[j].wh)) {
00687       perror ("vme_master_window_release");
00688       return(ERROR);
00689     }
00690   }
00691   /* Cleanup slot */
00692   table[j].wh = 0;
00693   return(MVME_SUCCESS);
00694 }
00695 /********************************************************************/
00696 /**
00697 Retrieve mapped address from mapped table.
00698 Check if the given address belongs to an existing map. If not will
00699 create a new map based on the address, current address modifier and
00700 the given size in bytes.
00701 @param *mvme VME structure
00702 @param  nbytes requested transfer size.
00703 @return MVME_SUCCESS, ERROR
00704 */
00705 mvme_addr_t vmic_mapcheck (MVME_INTERFACE *mvme, mvme_addr_t vme_addr, mvme_size_t n_bytes)
00706 {
00707   int j;
00708   VME_TABLE *table;
00709   mvme_addr_t addr;
00710   table = (VME_TABLE *) mvme->table;
00711   /* Extract window handle from table based on the VME address to read */
00712   for (j=0; table[j].valid; j++) {
00713     /* Check for the proper am */
00714     if (mvme->am != table[j].am)
00715       continue;
00716     /* Check the vme address range */
00717     if ((vme_addr >= table[j].low) && ((vme_addr+n_bytes) < table[j].high)) {
00718       /* valid range */
00719       break;
00720     }
00721   }
00722   // scan table
00723   /* Check if handle found or need to create new one */
00724   if (!table[j].valid) {
00725     /* Adjust vme_addr start point (split in quarters) */
00726     if (vme_addr > A32_CHUNK) 
00727       addr = vme_addr & (~A32_CHUNK);
00728     else
00729       addr = 0x00000000;
00730     /* Create a new window */
00731     if (vmic_mmap(mvme, addr, FullWsze(mvme->am)) != MVME_SUCCESS) {
00732       perror("cannot create vme map window");
00733       abort(); // cannot return anything!
00734     }
00735   }
00736   /* Get index in table in case new mapping has been requested */
00737   for (j=0; table[j].valid; j++) {
00738     /* Check for the proper am */
00739     if (mvme->am != table[j].am)
00740       continue;
00741     /* Check the vme address range */
00742     if ((vme_addr >= table[j].low) && ((vme_addr+n_bytes) < table[j].high)) {
00743       /* valid range */
00744       break;
00745     }
00746   } // scan table
00747   if (!table[j].valid) {
00748     perror("Map not found");
00749     abort(); // cannot return anything!
00750   }
00751   addr = (mvme_addr_t) (table[j].ptr) + (mvme_addr_t) (vme_addr - table[j].low);
00752   return addr;
00753 }
00754 
00755 /********************************************************************/
00756 /*-PAA- For test purpose only
00757   Allows code testing, in this case, the VMEIO board has been used. */
00758 
00759 #ifdef MAIN_ENABLE
00760 
00761 int main () {
00762 
00763   int status;
00764   int myinfo = VME_INTERRUPT_SIGEVENT;
00765 
00766   MVME_INTERFACE *myvme;
00767   int vmeio_status;
00768   
00769   /* Open VME channel */
00770   status = mvme_open(&myvme, 0);
00771   
00772   /* Reset VME */
00773   //  status = mvme_sysreset(myvme);
00774   
00775   /* Setup AM */
00776   status = mvme_set_am(myvme, 0x09);
00777   
00778   /* Setup Data size */
00779   status = mvme_set_dmode(myvme, MVME_DMODE_D32);
00780   
00781   /* Read VMEIO status */
00782   status = mvme_read(myvme, &vmeio_status, 0x4078001C, 4);
00783   printf("VMEIO status : 0x%x\n", vmeio_status);
00784   
00785   /* Write Single value */
00786   mvme_write_value(myvme, 0x40780010, 0x0);
00787   
00788   /* Read Single Value */
00789   printf("Value : 0x%lx\n", mvme_read_value(myvme, 0x40780018));
00790   
00791   /* Write Single value */
00792   mvme_write_value(myvme, 0x40780010, 0x3);
00793   
00794   /* Read Single Value */
00795   printf("Value : 0x%lx\n", mvme_read_value(myvme, 0x40780018));
00796   
00797   /* Write Single value */
00798   mvme_write_value(myvme, 0x40780008, 0xF);
00799   
00800   /* Write to the VMEIO in pulse mode */
00801 //  data = 0xF;
00802 //  for (;;) {
00803 //    status = mvme_write(myvme, 0x78000C, &data, 4);
00804 //    status = mvme_write(myvme, 0x78000C, &data, 4);
00805 //  }
00806   
00807 //------------ Interrupt section
00808   // IRQ 7, vector from switch 0x0 -> 0x80 -> ch 0 source
00809   mvme_interrupt_attach(myvme, 7, 0x10, myisr, &myinfo);
00810   
00811   //  for (;;) {    
00812   //  }
00813   //  mvme_interrupt_enable(myvme, 1, 0x00, &myinfo);
00814   
00815   //  mvme_interrupt_disable(myvme, 1, 0x00, &myinfo);
00816   
00817   
00818   mvme_interrupt_generate(myvme, 7, 0x10, &myinfo);
00819 
00820 
00821   //  mvme_interrupt_detach(myvme, 1, 0x00, &myinfo);
00822 
00823   /* Close VME channel */
00824   status = mvme_close(myvme);
00825   return 1;
00826 }
00827 
00828 #endif

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