• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

llif.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * File:
00004  *
00005  * $RCSfile: llif.c,v $
00006  * 
00007  * Copyright (C) 2001 D-TACQ Solutions Ltd
00008  * not to be used without owner's permission
00009  *
00010  * Description: implmentation of device driver interface for LLC
00011  *
00012  * $Id: llif.c,v 1.18.4.17 2006/02/22 10:25:47 pgm Exp $
00013  * $Log: llif.c,v $
00014  * Revision 1.18.4.17  2006/02/22 10:25:47  pgm
00015  * fix dbg snafu
00016  *
00017  * Revision 1.18.4.16  2006/02/15 10:10:03  pgm
00018  * *** empty log message ***
00019  *
00020  * Revision 1.18.4.15  2006/01/19 20:17:36  pgm
00021  * *** empty log message ***
00022  *
00023  * Revision 1.18.4.14  2006/01/19 20:15:28  pgm
00024  * *** empty log message ***
00025  *
00026  * Revision 1.18.4.13  2006/01/15 11:18:18  pgm
00027  * SYNC_2V
00028  *
00029  * Revision 1.18.4.12  2005/11/04 17:26:18  pgm
00030  * *** empty log message ***
00031  *
00032  * Revision 1.18.4.11  2005/10/22 12:18:56  pgm
00033  * *** empty log message ***
00034  *
00035  * Revision 1.18.4.10  2005/08/22 09:20:40  pgm
00036  * remove acq32 dependency
00037  *
00038  * Revision 1.18.4.9  2005/07/29 20:05:31  pgm
00039  * can find prams on cmdline
00040  *
00041  * Revision 1.18.4.8  2004/12/09 12:58:34  pgm
00042  * various attempts at repartitioning for speed
00043  *
00044  * Revision 1.18.4.7  2004/11/04 07:13:13  pgm
00045  * merged multicard case
00046  *
00047  * Revision 1.18.4.6.2.5  2004/09/28 06:00:06  pgm
00048  * two card case
00049  *
00050  * Revision 1.18.4.6.2.4  2004/09/26 19:50:58  pgm
00051  * *** empty log message ***
00052  *
00053  * Revision 1.18.4.6.2.3  2004/09/26 15:28:14  pgm
00054  * correct big buf mapping
00055  *
00056  * Revision 1.18.4.6.2.2  2004/09/26 11:32:39  pgm
00057  * multiboard tstats pollstats in
00058  *
00059  * Revision 1.18.4.6.2.1  2004/09/25 11:53:03  pgm
00060  * first pass multi done - check it works for n==1
00061  *
00062  * Revision 1.18.4.6  2004/09/15 16:59:27  pgm
00063  * llif.c
00064  *
00065  * Revision 1.18.4.5  2004/09/15 12:48:21  pgm
00066  * use internal var for llWaitDmaDone, reformat
00067  *
00068  * Revision 1.18.4.4  2004/08/10 07:35:46  pgm
00069  * works with ACQ196
00070  *
00071  * Revision 1.18.4.3  2004/07/27 20:49:06  pgm
00072  * llcontrol 2G with AO - in debug
00073  *
00074  * Revision 1.18.4.2  2004/07/25 20:39:38  pgm
00075  * hbpolling, 96 channels
00076  *
00077  * Revision 1.18.4.1  2004/07/25 20:34:59  pgm
00078  * ACQ196 pass 1
00079  *
00080  * Revision 1.18  2003/02/14 09:48:03  pgm
00081  * bigbuf def now comes from driver
00082  *
00083  * Revision 1.17  2002/09/25 09:50:49  pgm
00084  * opt to use bigbuf
00085  *
00086  * Revision 1.16  2002/09/02 16:26:24  pgm
00087  * USE_IOCTL_DOC
00088  *
00089  * Revision 1.15  2002/09/02 15:36:14  pgm
00090  * hook up int masking
00091  *
00092  * Revision 1.14  2002/09/02 11:01:18  pgm
00093  * revised debug levels
00094  *
00095  * Revision 1.13  2002/04/02 10:15:38  pgm
00096  * emacs indent, untabify
00097  *
00098  * Revision 1.12  2001/09/07 15:36:43  pgm
00099  * ioctl() version works
00100  *
00101  * Revision 1.11  2001/09/07 12:17:57  pgm
00102  * USE_IOCTL - access to regs by deref
00103  *
00104  * Revision 1.10  2001/08/23 20:00:50  pgm
00105  * mod protocol avoids races and works
00106  *
00107  * Revision 1.9  2001/05/25 13:12:42  pgm
00108  * embedded stats
00109  *
00110  * Revision 1.8  2001/05/25 12:05:15  pgm
00111  * its a runner - shippit quick
00112  *
00113  * Revision 1.7  2001/05/23 19:16:21  pgm
00114  * doc
00115  *
00116  * Revision 1.6  2001/05/21 17:42:38  pgm
00117  * reformed
00118  *
00119  * Revision 1.5  2001/05/20 21:24:10  pgm
00120  * ll WIP - almost works
00121  *
00122  * Revision 1.4  2001/05/19 19:46:15  pgm
00123  * enters LL mode with good bufs, mboxes
00124  *
00125  * Revision 1.3  2001/05/19 07:03:40  pgm
00126  * LL done for SOFT CLOCK, compiles
00127  *
00128  * Revision 1.2  2001/05/18 20:21:13  pgm
00129  * compiles. needs algorithms
00130  *
00131  * Revision 1.1  2001/05/18 07:09:37  pgm
00132  * first cut - wont compile :-(
00133  *
00134  * Revision 1.2  2000/12/28 11:03:00  pgm
00135  * *** empty log message ***
00136  *
00137  * Revision 1.1  1999/10/22 16:26:49  pgm
00138  * first entry to cvs
00139  *
00140  *
00141 \*****************************************************************************/
00142 
00143 /** @file llif.c  implementation of device driver interface for LLC.
00144  * define USE_IOCTL to use ioctls to access mbox. 
00145  *  this is slow, but guaranteed portable
00146  * 
00147  * if undefined, memory mapped accesss is used - much faster, but x86 only
00148  */
00149 
00150 //#define USE_IOCTL
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;                         // alternate - use ioctl to access
00191         r32* mailboxes;                 // or mapping (x86 only)
00192         u32 mailboxes_shadow[4];        // up to dat cache of write values
00193         u32 mailboxes_lastwrite[4];     // what did we write last ??
00194         r32 *inbound_q_port;            /* inbound on target */
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 // set a mail mbox register: ibox {0..3}. return 0 on success
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 // get contents of mailbox register: ibox {0..3}
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 // iboard {1..3}. return 0 on success
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         // IO not on page boundary - get the offset to adjust
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  * mmapDmaBuffer obtains a user space buffer
00396  * in virtual memory, this is mapped linearly
00397  * in physical memory, this is a series of 128K blocks
00398  *
00399  * if the allocated length < 128K, no problem, it's just linear memory
00400  *
00401  * clients should use getBusAddr to get the appropriate bus address for offset
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 // maps dma buffer, nbytes long. ret 0 on success
00430 // iboard {1..4}
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  * (1)open() a path to the device
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  * (2) mmap() a buffer
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  * (3) ioctl() - fetch the phys defs
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  * now decode the physical mem defs in buffer.
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 // returns mapped bus address for offset (bytes) 
00504 // warning: client is assumed not to go over the end of a segment
00505 // BUT client has no way of knowng where the end is ...
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  * mapping from bigbuf
00551  * work to do - should get consts from /proc/.acq32.globs ... meanwhile ...
00552  */
00553 //            acq32_big_buf_base:0x08000000
00554 //            acq32_big_buf_len:0x08000000
00555 
00556 #ifdef PGMCOMOUT
00557 #define ACQ32_BIG_BUF_BASE 0x08000000    /* physaddr of buffer base */
00558 #define ACQ32_BIG_BUF_LEN  0x08000000    /* buffer length in bytes  */
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  * 2G driver - returns bigbuf portion details on read of .host device
00603 
00604 [dt100@cp605 LOWLATENCY]$ cat /dev/acq32/acq32.7.host
00605 BIGBUF: pa=0x18000000 len=0x01000000
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 // maps dma buffer, nbytes long. ret 0 on success
00633 // iboard {1..4}
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  * (1)open() a path to the device
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  * (2) mmap() a buffer
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  * now decode the physical mem defs in buffer.
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   /* chances of 4 channels all having this val => 0*/
00703 
00704 
00705 
00706 static void udelay(int usecs)
00707 /* a wild guess at a microsecond delay. aim is to "rest" memory to let 
00708  * external DMA have accesss. We assume this code runs from cache ...
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 /* one shot buffer priming pre run */
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 /* return 0 on success */
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 

Generated on Wed Jan 5 2011 for llcontrol by  doxygen 1.7.1