00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 #include "local.h"
00154
00155
00156 #include <assert.h>
00157 #include "llif.h"
00158
00159 #include <stdio.h>
00160 #include <stdlib.h>
00161
00162 #include <errno.h>
00163 #include <fcntl.h>
00164 #include <sys/ioctl.h>
00165 #include <sys/mman.h>
00166 #include <sys/stat.h>
00167 #include <sys/types.h>
00168 #include <stdio.h>
00169 #include <unistd.h>
00170
00171
00172 #include "acq32ioctl.h"
00173
00174
00175
00176 #ifdef USE_IOCTL
00177 #define USE_IOCTL_DOC "USE_IOCTL - portable but slow"
00178 #else
00179 #define USE_IOCTL_DOC "NOT USE_IOCTL memory mapped - x86 only FAST"
00180 #endif
00181
00182
00183 #ifndef dbg
00184 #define dbg(level, fmt, arg...) fprintf(stderr, fmt, ## arg)
00185 #endif
00186
00187 typedef volatile u32 r32;
00188
00189 struct MU {
00190 int fd;
00191 r32* mailboxes;
00192 u32 mailboxes_shadow[4];
00193 u32 mailboxes_lastwrite[4];
00194 r32 *inbound_q_port;
00195 r32 *outbound_q_port;
00196
00197 int poll_count;
00198 };
00199
00200 #define FNAME_FMT "/dev/acq32/acq32.%d."
00201 #define FNAME_FMT_MBOX FNAME_FMT "raw"
00202 #define FNAME_FMT_DMABUF FNAME_FMT "01" // don't ask - this is a convenience
00203
00204 #define FNAME_FMT_HOST FNAME_FMT "host"
00205
00206 int setMbox( struct MU* m, int ibox, u32 value )
00207
00208 {
00209 #ifdef USE_IOCTL
00210 int rc;
00211 #endif
00212 assert( IN_RANGE( ibox, 0, 3 ) );
00213
00214
00215 PRINTF(3)( "setMbox( %d, 0x%08x )\n", ibox, value );
00216 #ifndef USE_IOCTL
00217 m->mailboxes[ibox] =
00218 #endif
00219 m->mailboxes_shadow[ibox] =
00220 m->mailboxes_lastwrite[ibox] = value;
00221
00222 #ifdef USE_IOCTL
00223 rc = ioctl( m->fd, ACQ32_IOSMBX(ibox), value );
00224
00225 PRINTF(3)( "ioctl( %d, %d, %08x ) returns %d\n",
00226 m->fd, ACQ32_IOSMBX(ibox), value, rc );
00227
00228 assert( rc >= 0 );
00229 #endif
00230 return 0;
00231 }
00232
00233 void showLastWrites( struct MU* m )
00234 {
00235 fprintf( stderr, "lastWrites()\n" );
00236 fprintf( stderr, "0x%08x 0x%08x 0x%08x 0x%08x\n",
00237 m->mailboxes_lastwrite[0],
00238 m->mailboxes_lastwrite[1],
00239 m->mailboxes_lastwrite[2],
00240 m->mailboxes_lastwrite[3] );
00241 }
00242 int setMboxBits( struct MU* m, int ibox, u32 bits_to_set )
00243 {
00244 assert( IN_RANGE( ibox, 0, 3 ) );
00245
00246 m->mailboxes[ibox] = m->mailboxes_shadow[ibox] |= bits_to_set;
00247 return 0;
00248 }
00249
00250 int clrMboxBits( struct MU* m, int ibox, u32 bits_to_clr )
00251 {
00252 assert( IN_RANGE( ibox, 0, 3 ) );
00253
00254 m->mailboxes[ibox] = m->mailboxes_shadow[ibox] &= ~bits_to_clr;
00255 return 0;
00256 }
00257
00258 int setMboxField( struct MU* m,
00259 int ibox, u32 field_mask, u32 field_value )
00260 {
00261 assert( IN_RANGE( ibox, 0, 3 ) );
00262
00263 m->mailboxes_shadow[ibox] &= ~field_mask;
00264 m->mailboxes_shadow[ibox] |= field_value;
00265 m->mailboxes[ibox] = m->mailboxes_shadow[ibox];
00266 return 0;
00267 }
00268
00269 u32 getMbox( struct MU* m, int ibox )
00270
00271 {
00272 u32 newval;
00273 #ifdef USE_IOCTL
00274 int rc;
00275 #endif
00276
00277 assert( IN_RANGE( ibox, 0, 3 ) );
00278
00279 #ifdef USE_IOCTL
00280 rc = ioctl( m->fd, ACQ32_IOGMBX(ibox), &newval );
00281 assert( rc >= 0 );
00282
00283 PRINTF(4)( "ioctl( %d, %d, %p ) output 0x%08x\n",
00284 m->fd, ACQ32_IOGMBX(ibox), &newval, newval );
00285 #else
00286 newval = m->mailboxes[ibox];
00287 #endif
00288
00289 if ( newval != m->mailboxes_shadow[ibox] ){
00290 PRINTF(4)( "getMbox( %d ) = 0x%08x\n",
00291 ibox, m->mailboxes_shadow[ibox] );
00292 }
00293
00294 m->mailboxes_shadow[ibox] = newval;
00295 return m->mailboxes_shadow[ibox];
00296 }
00297
00298 u32 getMboxShadow(struct MU* m, int ibox)
00299 {
00300 assert( IN_RANGE( ibox, 0, 3 ) );
00301 return m->mailboxes_shadow[ibox];
00302 }
00303
00304 u32 pollMboxBits( struct MU* m, int ibox, u32 mask, u32 goal )
00305 {
00306 int ipoll = 0;
00307 u32 mbtemp;
00308
00309 while( ( (mbtemp = getMbox( m, ibox ))&mask ) == 0 ){
00310 if ( (++ipoll&0x3ffff) == 0 ){
00311 fprintf( stderr,
00312 "pollMboxBits() mask:0x%08x goal:0x%08x got:0x%08x\n",
00313 mask, goal, mbtemp );
00314 }
00315 }
00316
00317 PRINTF(4)( "pollMboxBits() returning 0x%08x\n", mbtemp );
00318 return mbtemp;
00319 }
00320
00321
00322 void setMboxPollcount(struct MU* m, int poll_count)
00323 {
00324 m->poll_count = poll_count;
00325 }
00326 int getMboxPollcount(struct MU* m)
00327 {
00328 return m->poll_count;
00329 }
00330
00331
00332 struct MU* mmapMbox( int iboard )
00333
00334 {
00335 char fname[80];
00336
00337 void* region;
00338 struct MU* m = malloc( sizeof(struct MU) );
00339 unsigned offset;
00340
00341 assert( m != 0 );
00342 assert( IN_RANGE( iboard, 1, 8 ) );
00343
00344 sprintf( fname, FNAME_FMT_MBOX, iboard );
00345
00346 if ( (m->fd = open( fname, O_RDWR )) < 0 ){
00347 fprintf( stderr, "mmap: failed to open device \"%s\" - ", fname );
00348 perror( "" );
00349 exit( 1 );
00350 }
00351 #ifndef USE_IOCTL
00352 region = mmap( NULL, 0x400, PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, 0 );
00353
00354 if ( region == (void*)-1 ){
00355 char errbuf[256];
00356 sprintf(errbuf, "%s %s", "mmap", fname);
00357 perror(errbuf);
00358 exit( 1 );
00359 }
00360
00361
00362
00363 if ( ioctl( m->fd, ACQ32_IOG_PCIREGS_OFFSET, &offset ) != 0 ){
00364 perror( "ioctl ACQ32_IOG_PCIREGS_OFFSET" );
00365 exit( 1 );
00366 }
00367
00368 PRINTF(1)("mmap %p offset %d\n", region, offset);
00369 PRINTF(2)("data: %08x %08x %08x %08x\n",
00370 ((unsigned*)(region+offset))[0],
00371 ((unsigned*)(region+offset))[1],
00372 ((unsigned*)(region+offset))[2],
00373 ((unsigned*)(region+offset))[3] );
00374
00375 dbg(1, "mbox access mode %s\n", USE_IOCTL_DOC );
00376
00377 #ifndef __ACQ196__
00378 m->mailboxes = (r32*)((char*)region+offset+MAILBOX_0);
00379 #else
00380 m->mailboxes = (r32*)((char*)region+offset);
00381 m->inbound_q_port = (r32*)((char*)region+offset+0x30);
00382 m->outbound_q_port = (r32*)((char*)region+offset+0x34);
00383 #endif
00384 getMbox( m, 0 );
00385 getMbox( m, 1 );
00386 getMbox( m, 2 );
00387 getMbox( m, 3 );
00388 #endif
00389 dbg( 1, "mbox access mode %s\n", USE_IOCTL_DOC );
00390 return m;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 #define MAX_MAPPING 0x00100000 // 1MB is a handy # to play with
00405 #define MAX_SEG 0x00020000 // Linux maps 128k segments
00406
00407 #define MAX_SEGMENTS (MAX_MAPPING/MAX_SEG)
00408
00409 struct SegmentMap {
00410 int offset;
00411 int length;
00412 u32 physaddr;
00413 int pad;
00414 };
00415
00416
00417 struct DmaBuffer {
00418 u32* vaddr;
00419 int nbytes;
00420 struct SegmentMap seg_map[MAX_SEGMENTS];
00421 };
00422
00423 int getDmaBufferLen(struct DmaBuffer* buffer)
00424 {
00425 return buffer->nbytes;
00426 }
00427
00428 struct DmaBuffer* mmapDmaBuffer( int iboard, unsigned nbytes )
00429
00430
00431 {
00432 char fname[80];
00433 int fd_in;
00434 caddr_t* region;
00435 u32* phys_defs;
00436 int idef;
00437 u32 offset;
00438 int rc;
00439 struct DmaBuffer* d = malloc( sizeof( struct DmaBuffer ) );
00440
00441 assert( d != 0 );
00442
00443 sprintf( fname, FNAME_FMT_DMABUF, iboard );
00444
00445
00446
00447 if ( (fd_in = open( fname, O_RDWR )) < 0 ){
00448 fprintf( stderr, "mmap: failed to open device \"%s\" - ", fname );
00449 perror( "" );
00450 exit( 1 );
00451 }
00452
00453
00454
00455
00456
00457 region = mmap( NULL, nbytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd_in, 0 );
00458
00459 if ( region == (caddr_t*)-1 ){
00460 perror( "mmap" );
00461 exit( 1 );
00462 }
00463
00464
00465
00466
00467
00468 PRINTF(3)( "region is %p\n", region );
00469
00470 rc = ioctl( fd_in, ACQ32_IOREAD_GETPHYSICAL, region );
00471
00472 if ( rc < 0 ){
00473 perror( "ioctl ACQ32_IOREAD_GETPHYSICAL failed" );
00474 exit( 1 );
00475 }
00476
00477
00478
00479
00480 phys_defs = (u32*)region;
00481
00482 for ( idef = 0, offset = 0; idef != MAX_SEGMENTS; idef += 1 ){
00483 if ( phys_defs[idef*2] == 0 ){
00484 PRINTF(3)( "quitting after %d segments\n", idef );
00485 break;
00486 }else{
00487 PRINTF(3)( "adding segment %d at offset 0x%08x phys 0x%08x"
00488 " len 0x%08x\n",
00489 idef, offset, phys_defs[idef*2], phys_defs[idef*2+1] );
00490 d->seg_map[idef].offset = offset;
00491 d->seg_map[idef].physaddr = phys_defs[idef*2];
00492 d->seg_map[idef].length = phys_defs[idef*2+1];
00493 offset += phys_defs[idef*2+1];
00494 }
00495 }
00496
00497 d->vaddr = (u32*)region;
00498 d->nbytes = nbytes;
00499 return d;
00500 }
00501
00502 u32 getBusAddr( struct DmaBuffer* d, u32 offset )
00503
00504
00505
00506 {
00507 int idef;
00508
00509 for ( idef = 0; idef != MAX_SEGMENTS; ++idef ){
00510 if ( offset >= d->seg_map[idef].offset &&
00511 offset < d->seg_map[idef].offset + d->seg_map[idef].length ){
00512 return d->seg_map[idef].physaddr + offset -
00513 d->seg_map[idef].offset;
00514 }
00515 }
00516
00517 return 0;
00518 }
00519
00520 u32* getVaddr( struct DmaBuffer* db, u32 offset )
00521 {
00522 if ( offset < db->nbytes ){
00523 PRINTF(4)( "getVaddr %p %d %p\n", db->vaddr, offset,
00524 &db->vaddr[offset/sizeof(u32)] );
00525
00526 return &db->vaddr[offset/sizeof(u32)];
00527 }else{
00528 return 0;
00529 }
00530 }
00531
00532 void acq32_enableInts( struct MU* mbx, unsigned mask )
00533 {
00534 if ( ioctl( mbx->fd, ACQ32_IOS_INTS_ENABLE, mask ) != 0 ){
00535 perror( "ioctl ACQ32_IOS_INTS_ENABLE" );
00536 exit( 1 );
00537 }
00538 }
00539 void acq32_maskInts( struct MU* mbx, unsigned mask )
00540 {
00541 if ( ioctl( mbx->fd, ACQ32_IOS_INTS_DISABLE, mask ) != 0 ){
00542 perror( "ioctl ACQ32_IOS_INTS_DISABLE" );
00543 exit( 1 );
00544 }
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 #ifdef PGMCOMOUT
00557 #define ACQ32_BIG_BUF_BASE 0x08000000
00558 #define ACQ32_BIG_BUF_LEN 0x08000000
00559 #else
00560 #define ACQ32_BIG_BUF_BASE acq32_big_buf_base
00561 #define ACQ32_BIG_BUF_LEN acq32_big_buf_len
00562
00563 static int acq32_big_buf_base;
00564 static int acq32_big_buf_len;
00565
00566 static void _getBigBufPrams()
00567 {
00568 FILE* fp = fopen( "/proc/.acq200.globs", "r" );
00569 char buf[80];
00570
00571 assert( fp != 0 );
00572
00573 while( fgets( buf, sizeof(buf), fp ) ){
00574 if (sscanf(buf,
00575 " acq32_big_buf_base:0x%x", &acq32_big_buf_base)){
00576 PRINTF(1)("acq32_big_buf_base set %x\n",
00577 acq32_big_buf_base);
00578 }
00579 if (sscanf(buf,
00580 " acq32_big_buf_len:0x%x", &acq32_big_buf_len)){
00581 PRINTF(1)("acq32_big_buf_len set %x\n",
00582 acq32_big_buf_len);
00583 }
00584 }
00585 }
00586
00587 static void getBigBufPrams()
00588 {
00589 const char* base = getenv("acq32_big_buf_base");
00590 const char* len = getenv("acq32_big_buf_len");
00591
00592 if (len != 0 && base != 0){
00593 acq32_big_buf_base = strtoul(base, 0, 0);
00594 acq32_big_buf_len = strtoul(base, 0, 0);
00595 }else{
00596 _getBigBufPrams();
00597 }
00598 }
00599 #endif
00600
00601
00602
00603
00604
00605
00606
00607
00608 static void acq196_get_physical(int fd, struct DmaBuffer* d)
00609 {
00610 char myline[80];
00611 FILE* fp = fdopen(fd, "r");
00612
00613 if (fp == 0){
00614 perror("FAILED fdopen");
00615 exit(errno);
00616 }
00617
00618 if (fgets(myline, sizeof(myline)-1, fp) &&
00619 sscanf(myline,
00620 "BIGBUF: pa=0x%x len=0x%x",
00621 &d->seg_map[0].physaddr,
00622 &d->seg_map[0].length) == 2 ){
00623 ;
00624 }else{
00625 perror("FAILED to read data from file.\n"
00626 "Please check driver is up to date\n");
00627 }
00628 fclose(fp);
00629 }
00630
00631 struct DmaBuffer* mmapBigBuffer( int iboard, unsigned nbytes )
00632
00633
00634 {
00635 #define FN "mmapDmaBuffer() "
00636 char fname[80];
00637 int fd_in;
00638 caddr_t* region;
00639 struct DmaBuffer* d = malloc( sizeof( struct DmaBuffer ) );
00640
00641 assert( d != 0 );
00642
00643 getBigBufPrams();
00644
00645 sprintf( fname, FNAME_FMT_HOST, iboard );
00646
00647
00648
00649 if ( (fd_in = open( fname, O_RDWR )) < 0 ){
00650 fprintf(stderr, "mmap:failed to open device \"%s\" - ", fname);
00651 perror( "" );
00652 exit( 1 );
00653 }
00654
00655
00656
00657
00658 #ifdef __ACQ196__
00659 nbytes = 0x01000000;
00660 PRINTF(1)(FN"ask for full bigbuf portion %x\n", nbytes);
00661 #endif
00662 nbytes = MIN( nbytes, ACQ32_BIG_BUF_LEN );
00663
00664 PRINTF(1)( FN"map at most %d bytes\n", nbytes );
00665
00666 region = mmap( NULL, nbytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd_in, 0 );
00667
00668 if ( region == (caddr_t*)-1 ){
00669 perror( "mmap" );
00670 exit( 1 );
00671 }
00672
00673 #ifdef __ACQ196__
00674 acq196_get_physical(fd_in, d);
00675 #else
00676
00677
00678
00679 d->seg_map[0].physaddr = ACQ32_BIG_BUF_BASE;
00680 d->seg_map[0].length = ACQ32_BIG_BUF_LEN;
00681 #endif
00682 d->seg_map[0].offset = 0;
00683 d->vaddr = (u32*)region;
00684 d->nbytes = nbytes;
00685
00686 PRINTF(1)( FN "physaddr 0x%08x vaddr 0x%08x\n",
00687 d->seg_map[0].physaddr, (u32)d->vaddr );
00688
00689 return d;
00690 #undef FN
00691 }
00692
00693
00694 void mmapValidateDmaBuffer( struct MU* m, int nsamples )
00695 {
00696 if ( ioctl( m->fd, ACQ32_IOS_VALIDATE_BIGBUF, nsamples ) != 0 ){
00697 perror( "ioctl ACQ32_IOS_VALIDATE_BIGBUF" );
00698 exit( 1 );
00699 }
00700 }
00701
00702 #define INITBUF_MARKER 0x1100c0de
00703
00704
00705
00706 static void udelay(int usecs)
00707
00708
00709
00710 {
00711 volatile int ii;
00712
00713 while(usecs--){
00714 for(ii = 0x10; --ii;){
00715 ;
00716 }
00717 }
00718 }
00719
00720 void hbPrimeBuffer(struct DmaBuffer *buf)
00721
00722 {
00723 #ifdef __ACQ196__
00724 memset32(buf->vaddr, INITBUF_MARKER, 0x00f00000/sizeof(u32));
00725 #else
00726 #error WORKTODO - __ACQ196__ not defined
00727 #endif
00728 }
00729 void hbPrimePoll(struct DmaBuffer *buf, int offset, int sample_len)
00730 {
00731 int end32 = (offset + sample_len)/sizeof(u32);
00732 volatile u32* marker = &buf->vaddr[end32-2];
00733
00734 marker[0] = INITBUF_MARKER;
00735 marker[1] = INITBUF_MARKER;
00736 }
00737 int hbPoll(
00738 struct DmaBuffer *buf, int offset, int sample_len,
00739 volatile int *user_abort)
00740 {
00741 int end32 = (offset + sample_len)/sizeof(u32);
00742 volatile u32* marker = &buf->vaddr[end32-2];
00743 int ipoll = 1;
00744 int reported = 0;
00745
00746 while (marker[0] == INITBUF_MARKER && marker[1] == INITBUF_MARKER){
00747 udelay(1);
00748 ++ipoll;
00749 if (ipoll > 10000 && !reported){
00750 PRINTF(1)("hbPoll looking at %p\n", marker);
00751 reported = 1;
00752 }
00753 if (*user_abort){
00754 break;
00755 }
00756 }
00757
00758 return ipoll;
00759 }
00760
00761
00762 MFA mu_reserveOutbound(struct MU* mu)
00763 {
00764 return *mu->inbound_q_port;
00765 }
00766 int mu_putOutbound(struct MU* mu, MFA mfa)
00767
00768 {
00769 *mu->inbound_q_port = mfa;
00770 return 0;
00771 }
00772
00773
00774 MFA mu_getInbound(struct MU* mu)
00775 {
00776 return *mu->outbound_q_port;
00777 }
00778 int mu_returnInbound(struct MU* mu, MFA mfa)
00779 {
00780 *mu->outbound_q_port = mfa;
00781 return 0;
00782 }
00783