00001
00002
00003
00004
00005
00006
00007
00008
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
00041
00042
00043
00044 mvme_size_t FullWsze (int am) {
00045 switch (am & 0xF0) {
00046 case 0x00:
00047 return A32_CHUNK;
00048 case 0x30:
00049 return 0xFFFFFF;
00050 case 0x20:
00051 return 0xFFFF;
00052 default:
00053 return 0;
00054 }
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 int mvme_open(MVME_INTERFACE **mvme, int index)
00066 {
00067 DMA_INFO *info;
00068
00069
00070 if (index != 0) {
00071 perror("Invalid parameter (index != 0");
00072 (*mvme)->handle = 0;
00073 return(MVME_INVALID_PARAM);
00074 }
00075
00076
00077 *mvme = (MVME_INTERFACE *) calloc(1, sizeof(MVME_INTERFACE));
00078
00079
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
00087 (*mvme)->table = (char *) calloc(MAX_VME_SLOTS, sizeof(VME_TABLE));
00088
00089
00090 (*mvme)->am = MVME_AM_DEFAULT;
00091
00092
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
00099 info = (DMA_INFO *) calloc(1, sizeof(DMA_INFO));
00100
00101 (*mvme)->info = info;
00102
00103 while (1) {
00104
00105
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
00147
00148
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
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
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 free (mvme->info);
00185
00186
00187
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 }
00194
00195
00196 free (mvme->table);
00197 mvme->table = NULL;
00198
00199
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
00208 free (mvme);
00209
00210 return(MVME_SUCCESS);
00211 }
00212
00213
00214
00215
00216
00217
00218
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
00232
00233
00234
00235
00236
00237
00238
00239
00240
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
00247
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
00302 #endif
00303 } else {
00304 int i;
00305 mvme_addr_t addr;
00306
00307
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
00337
00338
00339
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
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
00362
00363
00364
00365
00366
00367
00368
00369 int mvme_write(MVME_INTERFACE *mvme, mvme_addr_t vme_addr, void *src, mvme_size_t n_bytes)
00370 {
00371
00372
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
00402 addr = vmic_mapcheck(mvme, vme_addr, n_bytes);
00403
00404
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
00431
00432
00433
00434
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
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
00498
00499
00500
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
00518
00519
00520
00521
00522
00523
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
00533 event.sigev_signo = SIGIO;
00534 event.sigev_notify = SIGEV_SIGNAL;
00535 event.sigev_value.sival_int = 0;
00536
00537
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
00580
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
00593
00594
00595
00596
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
00607 j=0;
00608 while (table[j].valid) j++;
00609
00610 if (j < MAX_VME_SLOTS) {
00611
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
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
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
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
00649 return(MVME_ACCESS_ERROR);
00650 }
00651
00652 return(MVME_SUCCESS);
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
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
00669 for (j=0; table[j].valid; j++) {
00670
00671 if ((vme_addr == table[j].low) && ((vme_addr+size) == table[j].high)) {
00672
00673 break;
00674 }
00675 }
00676 if (!table[j].valid) {
00677
00678 return(MVME_SUCCESS);
00679 }
00680
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
00692 table[j].wh = 0;
00693 return(MVME_SUCCESS);
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
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
00712 for (j=0; table[j].valid; j++) {
00713
00714 if (mvme->am != table[j].am)
00715 continue;
00716
00717 if ((vme_addr >= table[j].low) && ((vme_addr+n_bytes) < table[j].high)) {
00718
00719 break;
00720 }
00721 }
00722
00723
00724 if (!table[j].valid) {
00725
00726 if (vme_addr > A32_CHUNK)
00727 addr = vme_addr & (~A32_CHUNK);
00728 else
00729 addr = 0x00000000;
00730
00731 if (vmic_mmap(mvme, addr, FullWsze(mvme->am)) != MVME_SUCCESS) {
00732 perror("cannot create vme map window");
00733 abort();
00734 }
00735 }
00736
00737 for (j=0; table[j].valid; j++) {
00738
00739 if (mvme->am != table[j].am)
00740 continue;
00741
00742 if ((vme_addr >= table[j].low) && ((vme_addr+n_bytes) < table[j].high)) {
00743
00744 break;
00745 }
00746 }
00747 if (!table[j].valid) {
00748 perror("Map not found");
00749 abort();
00750 }
00751 addr = (mvme_addr_t) (table[j].ptr) + (mvme_addr_t) (vme_addr - table[j].low);
00752 return addr;
00753 }
00754
00755
00756
00757
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
00770 status = mvme_open(&myvme, 0);
00771
00772
00773
00774
00775
00776 status = mvme_set_am(myvme, 0x09);
00777
00778
00779 status = mvme_set_dmode(myvme, MVME_DMODE_D32);
00780
00781
00782 status = mvme_read(myvme, &vmeio_status, 0x4078001C, 4);
00783 printf("VMEIO status : 0x%x\n", vmeio_status);
00784
00785
00786 mvme_write_value(myvme, 0x40780010, 0x0);
00787
00788
00789 printf("Value : 0x%lx\n", mvme_read_value(myvme, 0x40780018));
00790
00791
00792 mvme_write_value(myvme, 0x40780010, 0x3);
00793
00794
00795 printf("Value : 0x%lx\n", mvme_read_value(myvme, 0x40780018));
00796
00797
00798 mvme_write_value(myvme, 0x40780008, 0xF);
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 mvme_interrupt_attach(myvme, 7, 0x10, myisr, &myinfo);
00810
00811
00812
00813
00814
00815
00816
00817
00818 mvme_interrupt_generate(myvme, 7, 0x10, &myinfo);
00819
00820
00821
00822
00823
00824 status = mvme_close(myvme);
00825 return 1;
00826 }
00827
00828 #endif