LLC2_API
llif26.cpp
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * File:
00004  *
00005  * $RCSfile: llif26.c,v $
00006  * 
00007  * Copyright (C) 2001 D-TACQ Solutions Ltd
00008  * not to be used without owner's permission
00009  *
00010  * Description: implementation of device driver interface for LLC
00011  *
00012  * $Id: llif26.c,v 1.4 2010/08/26 16:25:52 pgm Exp $
00013  * $Log: llif26.c,v $
00014  * Revision 1.4  2010/08/26 16:25:52  pgm
00015  * more switchable instrumentation
00016  *
00017  * Revision 1.3  2007/05/01 19:22:04  pgm
00018  * linux26 device index from 0
00019  *
00020  * Revision 1.2  2007/02/19 15:22:23  pgm
00021  * *** empty log message ***
00022  *
00023  * Revision 1.1  2006/06/19 13:13:30  pgm
00024  * *** empty log message ***
00025  *
00026  * Revision 1.18.4.17  2006/02/22 10:25:47  pgm
00027  * fix dbg snafu
00028  *
00029  *
00030  *
00031 \*****************************************************************************/
00032 
00033 /** @file llif26.c  implementation of device driver interface 
00034  * for LLC for kernel .2.6x.
00035  */
00036 
00037 
00038 #include "local.h"
00039 
00040 
00041 #include <assert.h>
00042 #include "llif.h"
00043 
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 
00047 #include <errno.h>
00048 #include <fcntl.h>
00049 #include <sys/ioctl.h>
00050 #include <sys/mman.h>
00051 #include <sys/stat.h>
00052 #include <sys/types.h>
00053 #include <stdio.h>
00054 #include <unistd.h>
00055 
00056 
00057 //#include "acq32ioctl.h"
00058 #include "acq200_ioctl.h"
00059 
00060 int verbose;
00061 
00062 
00063 #ifndef dbg
00064 #define dbg(level, fmt, arg...)  fprintf(stderr, fmt, ## arg)
00065 #endif
00066 
00067 typedef volatile u32 r32;
00068 
00069 struct MU {
00070         int fd;                         // alternate - use ioctl to access
00071         r32* mailboxes;                 // or mapping (x86 only)
00072         u32 mailboxes_shadow[4];        // up to dat cache of write values
00073         u32 mailboxes_lastwrite[4];     // what did we write last ??
00074         int poll_count;
00075 };
00076 
00077 #define FNAME_FMT        "/dev/acq32/acq32.%d."
00078 #define FNAME_FMT_MBOX   FNAME_FMT "raw"
00079 
00080 #define FNAME_FMT_HOST   FNAME_FMT "host"
00081 
00082 #define FMT_SYS_PARAMS  "/sys/module/acq200_hostdrv/parameters/"
00083 #define FMT_SYS_SLOTS           FMT_SYS_PARAMS "slots"
00084 
00085 #define FMT_SYS_DEV "/sys/class/acqX00/acq200.%d/device/"
00086 #define FMT_SYS_DEV_HOST_PA     FMT_SYS_DEV "host_pa"
00087 #define FMT_SYS_DEV_HOST_LEN    FMT_SYS_DEV "host_len"
00088 
00089 #define FMT_IMASK       "/dev/acq200/acq200.%d.imask"
00090 
00091 static int lookup_device_index(int slot)
00092 {
00093         static int mapping[16];
00094         static int valid;
00095         int rc;
00096         
00097         if (!valid){
00098                 char slotdef[128];              
00099                 int ii;
00100                 FILE *fp;               
00101                 
00102                 fp = fopen(FMT_SYS_SLOTS, "r");
00103                 if (!fp){
00104                         fprintf(stderr, "Failed to open slot mapping:\"%s\"", 
00105                                 FMT_SYS_SLOTS); 
00106                         exit(errno);
00107                 }
00108                                 
00109                 for (ii = 0; ii < 16; ++ii){
00110                         mapping[ii] = -1;       
00111                 }
00112                 if (fgets(slotdef, 128, fp)){
00113                         char *cp;
00114                         for (cp = slotdef, ii = 0; 
00115                                 ii < 16 && (cp = strtok(cp, ",")) != 0; 
00116                                 cp = 0, ++ii){
00117                                         
00118                                 int slot_num = atoi(cp);
00119                                 assert(IN_RANGE(slot_num, 0, 15));
00120                                 if (slot_num != 0){
00121                                         mapping[slot_num] = ii;         
00122                                 }       
00123                         }
00124                 }                               
00125                 valid = 1;      
00126         }
00127         
00128         rc = mapping[slot];
00129         if (rc == -1){
00130                 fprintf(stderr, "No device found for slot %d", slot);
00131                 exit(-1);       
00132         }
00133         return rc;
00134 }
00135 static unsigned host_len(int iboard) {
00136         char fname[80];
00137         char line[80];
00138         char *my_line;
00139         unsigned len = 0;
00140         int rc;
00141         
00142         sprintf(fname, FMT_SYS_DEV_HOST_LEN, lookup_device_index(iboard));
00143         FILE *fp = fopen(fname, "r");
00144         assert(fp);
00145 
00146         my_line = fgets(line, sizeof(line), fp);
00147         assert(my_line);
00148         
00149         rc = sscanf(my_line, "%u", &len);
00150         assert(rc);
00151         return len;
00152 }
00153 static unsigned host_pa(int iboard) {
00154         char fname[80];
00155         char line[80];
00156         char *my_line;
00157         unsigned pa = 0;
00158         int rc;
00159 
00160         sprintf(fname, FMT_SYS_DEV_HOST_PA, lookup_device_index(iboard));
00161         FILE *fp = fopen(fname, "r");
00162         assert(fp);
00163 
00164         my_line = fgets(line, sizeof(line), fp);
00165         assert(my_line);
00166         
00167         rc = sscanf(my_line, "0x%x", &pa);
00168         assert(rc);
00169         return pa;
00170 }
00171 
00172 int setMbox( struct MU* m, int ibox, u32 value )      
00173 // set a mail mbox register: ibox {0..3}. return 0 on success
00174 {
00175         assert( IN_RANGE( ibox, 0, 3 ) );
00176 
00177     
00178         PRINTF(3)( "setMbox( %d, 0x%08x ) @%p\n", ibox, value,  &m->mailboxes[ibox]);
00179         m->mailboxes[ibox] = 
00180                 m->mailboxes_shadow[ibox] = 
00181                 m->mailboxes_lastwrite[ibox] = value;    
00182 
00183         return 0;   
00184 }    
00185 
00186 void showLastWrites( struct MU* m )
00187 {
00188         fprintf( stderr, "lastWrites()\n" );
00189         fprintf( stderr, "0x%08x  0x%08x  0x%08x  0x%08x\n",
00190                  m->mailboxes_lastwrite[0],
00191                  m->mailboxes_lastwrite[1],
00192                  m->mailboxes_lastwrite[2],
00193                  m->mailboxes_lastwrite[3] );
00194 }
00195 int setMboxBits( struct MU* m, int ibox, u32 bits_to_set )
00196 {
00197         assert( IN_RANGE( ibox, 0, 3 ) );
00198     
00199         m->mailboxes[ibox] = m->mailboxes_shadow[ibox] |= bits_to_set;
00200         return 0;
00201 }
00202 
00203 int clrMboxBits( struct MU* m, int ibox, u32 bits_to_clr )
00204 {
00205         assert( IN_RANGE( ibox, 0, 3 ) );
00206     
00207         m->mailboxes[ibox] = m->mailboxes_shadow[ibox] &= ~bits_to_clr;
00208         return 0;
00209 }
00210 
00211 int setMboxField( struct MU* m, 
00212                   int ibox, u32 field_mask, u32 field_value )
00213 {
00214         assert( IN_RANGE( ibox, 0, 3 ) );
00215     
00216         m->mailboxes_shadow[ibox] &= ~field_mask;
00217         m->mailboxes_shadow[ibox] |= field_value;
00218         m->mailboxes[ibox] = m->mailboxes_shadow[ibox];
00219         return 0;
00220 }
00221 
00222 u32 getMbox( struct MU* m, int ibox )      
00223 // get contents of mailbox register: ibox {0..3}
00224 {
00225         u32 newval;
00226     
00227         assert( IN_RANGE( ibox, 0, 3 ) );
00228 
00229         newval = m->mailboxes[ibox];
00230     
00231         if (newval != m->mailboxes_shadow[ibox] ){
00232                 PRINTF(4)( "getMbox( %d ) was:0x%08x now:0x%08x\n", 
00233                            ibox, m->mailboxes_shadow[ibox],
00234                            newval);
00235         }
00236     
00237         m->mailboxes_shadow[ibox] = newval;
00238         return m->mailboxes_shadow[ibox];
00239 }
00240 
00241 u32 getMboxShadow(struct MU* m, int ibox)
00242 {
00243         assert( IN_RANGE( ibox, 0, 3 ) );
00244         return m->mailboxes_shadow[ibox];
00245 }
00246 
00247 u32 pollMboxBits( struct MU* m, int ibox, u32 mask, u32 goal )
00248 {
00249         int ipoll = 0;
00250         u32 mbtemp;
00251     
00252         while( ( (mbtemp = getMbox( m, ibox ))&mask ) == 0 ){
00253                 if ( (++ipoll&0x3ffff) == 0 ){
00254                         fprintf( stderr, 
00255                                  "pollMboxBits() mask:0x%08x goal:0x%08x got:0x%08x\n",
00256                                  mask, goal, mbtemp       );
00257                 }
00258         }
00259     
00260         PRINTF(4)( "pollMboxBits() returning 0x%08x\n", mbtemp );
00261         return mbtemp;
00262 }
00263 
00264 
00265 void setMboxPollcount(struct MU* m, int poll_count)
00266 {
00267         m->poll_count = poll_count;
00268 }
00269 int getMboxPollcount(struct MU* m)
00270 {
00271         return m->poll_count;
00272 }
00273 
00274 
00275 struct MU* mmapMbox( int iboard )   
00276 // iboard {1..3}. return 0 on success
00277 {
00278         char fname[80];
00279 
00280         char* region;
00281         struct MU* m = (struct MU*)malloc( sizeof(struct MU) );
00282         unsigned offset;
00283 
00284         assert( m != 0 );
00285         memset(m, 0, sizeof(struct MU));
00286         assert( IN_RANGE( iboard, 1, 8 ) );
00287     
00288         sprintf( fname, FNAME_FMT_MBOX, iboard );
00289 
00290         if ( (m->fd = open( fname, O_RDWR )) < 0 ){
00291                 fprintf( stderr, "mmap: failed to open device \"%s\" - ", fname );
00292                 perror( "" );
00293                 exit( 1 );
00294         }
00295 
00296         region = (char*)mmap( NULL, 0x400, PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, 0 );
00297 
00298         if ( region == (void*)-1 ){
00299                 char errbuf[256];
00300                 sprintf(errbuf, "%s %s", "mmap", fname);
00301                 perror(errbuf);
00302                 exit( 1 );
00303         }
00304     
00305 
00306         offset = 16;
00307 
00308         PRINTF(1)("mmap %p offset %d\n", region, offset);
00309         PRINTF(2)("data: %08x %08x %08x %08x\n",
00310                   ((unsigned*)(region+offset))[0],
00311                   ((unsigned*)(region+offset))[1],
00312                   ((unsigned*)(region+offset))[2],
00313                   ((unsigned*)(region+offset))[3] );
00314 
00315 
00316         m->mailboxes = (r32*)((char*)region+offset);
00317 
00318         getMbox( m, 0 );
00319         getMbox( m, 1 );
00320         getMbox( m, 2 );
00321         getMbox( m, 3 );
00322 
00323         return m;
00324 }
00325 
00326 
00327 /*
00328  * mmapDmaBuffer obtains a user space buffer
00329  * in virtual memory, this is mapped linearly
00330  * in physical memory, this is a series of 128K blocks
00331  *
00332  * if the allocated length < 128K, no problem, it's just linear memory
00333  *
00334  * clients should use getBusAddr to get the appropriate bus address for offset
00335  */
00336  
00337 struct DmaBuffer {
00338         u32* vaddr;
00339         int nbytes;
00340         u32 physaddr;
00341 };
00342 
00343 int getDmaBufferLen(struct DmaBuffer* buffer)
00344 {
00345         return buffer->nbytes;
00346 }
00347 
00348 
00349 u32 getBusAddr( struct DmaBuffer* d, u32 offset_bytes)
00350 // returns mapped bus address for offset (bytes) 
00351 // warning: client is assumed not to go over the end of a segment
00352 // BUT client has no way of knowng where the end is ...
00353 {
00354         int idef;
00355     
00356         return d->physaddr + offset_bytes;
00357 }
00358 
00359 u32* getVaddr( struct DmaBuffer* db, u32 offset_bytes)
00360 {
00361         if (offset_bytes < db->nbytes){
00362                 PRINTF(4)( "getVaddr %p %d %p\n", db->vaddr, offset_bytes,
00363                            &db->vaddr[offset_bytes/sizeof(u32)] );
00364         
00365                 return &db->vaddr[offset_bytes/sizeof(u32)];
00366         }else{
00367                 return 0;
00368         }
00369 }
00370 
00371 void acq32_enableInts( struct MU* mbx, unsigned mask )
00372 {
00373         PRINTF(1)( "STUBBED\n");
00374 #if 0
00375         if ( ioctl( mbx->fd, ACQ32_IOS_INTS_ENABLE, mask ) != 0 ){
00376                 perror( "ioctl ACQ32_IOS_INTS_ENABLE" );
00377                 exit( 1 );
00378         }
00379 #endif
00380 }
00381 void acq32_maskInts( struct MU* mbx, unsigned mask )
00382 {
00383         PRINTF(1)( "STUBBED\n");
00384 #if 0
00385         if ( ioctl( mbx->fd, ACQ32_IOS_INTS_DISABLE, mask ) != 0 ){
00386                 perror( "ioctl ACQ32_IOS_INTS_DISABLE" );
00387                 exit( 1 );
00388         }
00389 #endif
00390 }
00391 
00392 
00393 
00394 struct DmaBuffer* mmapBigBuffer( int iboard, unsigned nbytes )
00395 // maps dma buffer, nbytes long. ret 0 on success
00396 // iboard {1..4}
00397 {
00398 #define FN "mmapDmaBuffer() "
00399         char fname[80];
00400         int fd_in;
00401         caddr_t* region;
00402         struct DmaBuffer* d = new DmaBuffer;
00403     
00404         assert( d != 0 );
00405 
00406 
00407 
00408         sprintf(fname, FNAME_FMT_HOST, iboard );
00409 
00410         PRINTF(1)(FN"01: open %s\n", fname);
00411 /*
00412  * (1)open() a path to the device
00413  */
00414         if ( (fd_in = open( fname, O_RDWR )) < 0 ){
00415                 fprintf(stderr, "mmap:failed to open device \"%s\" - ", fname);
00416                 perror( "" );
00417                 exit( 1 );
00418         }
00419 
00420 /*
00421  * (2) mmap() a buffer
00422  */
00423         nbytes = host_len(iboard);
00424         PRINTF(1)(FN"ask for full bigbuf portion %x\n", nbytes);
00425 
00426         region = (caddr_t*)mmap( NULL, nbytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd_in, 0 );
00427 
00428         if ( region == (caddr_t*)-1 ){
00429                 perror( "mmap" );
00430                 exit( 1 );
00431         }
00432 
00433         d->physaddr = host_pa(iboard);
00434         d->vaddr = (u32*)region;
00435         d->nbytes = nbytes;
00436 
00437         memset(region, 'I', nbytes);
00438 
00439         PRINTF(1)( FN "fd_in:%d physaddr 0x%08x vaddr %p len %d\n",
00440                         fd_in, d->physaddr, d->vaddr, d->nbytes);
00441 
00442 #if 0
00443         FILE *fp = fopen("host0.dat", "w");
00444         fwrite(d->vaddr, 1, d->nbytes, fp);
00445         fclose(fp);
00446 #endif
00447         memset(d->vaddr, 0, d->nbytes);
00448 
00449         PRINTF(1)(FN "written host0.dat, zeroed\n");
00450         return d;
00451 #undef FN    
00452 }
00453 
00454 
00455 void mmapValidateDmaBuffer( struct MU* m, int nsamples )
00456 {
00457 
00458 }
00459 
00460 #define INITBUF_MARKER 0x1100c0de   /* chances of 4 channels all having this val => 0*/
00461 
00462 
00463 
00464 static void udelay(int usecs)
00465 /* a wild guess at a microsecond delay. aim is to "rest" memory to let 
00466  * external DMA have accesss. We assume this code runs from cache ...
00467  */
00468 {
00469         volatile int ii;
00470 
00471         while(usecs--){
00472                 for(ii = 0x10; --ii;){
00473                         ;
00474                 }
00475         }
00476 }
00477 
00478 void hbPrimeBuffer(struct DmaBuffer *buf)
00479 /* one shot buffer priming pre run */
00480 {
00481         int len = buf->nbytes - 0x100000;
00482 
00483         assert(len > 0);
00484 
00485         memset32(buf->vaddr, INITBUF_MARKER, len/sizeof(u32));
00486 }
00487 
00488 void hbPrimePoll(struct DmaBuffer *buf, int offset, int sample_len)
00489 {
00490         int end32 = (offset + sample_len)/sizeof(u32);
00491         volatile u32* marker = &buf->vaddr[end32-2];
00492 
00493         marker[0] = INITBUF_MARKER;
00494         marker[1] = INITBUF_MARKER;
00495 }
00496 int hbPoll(
00497         struct DmaBuffer *buf, int offset, int sample_len,
00498         volatile int *user_abort)
00499 {
00500         int end32 = (offset + sample_len)/sizeof(u32);
00501         volatile u32* marker = &buf->vaddr[end32-2];
00502         int ipoll = 1;
00503         int reported = 0;
00504 
00505         while (marker[0] == INITBUF_MARKER && marker[1] == INITBUF_MARKER){
00506                 udelay(1);
00507                 ++ipoll;
00508                 if (ipoll > 10000 && !reported){
00509                         PRINTF(1)("hbPoll looking at %p\n", marker);
00510                         reported = 1;
00511                 }
00512                 if (*user_abort){
00513                         break;
00514                 }
00515         }
00516 
00517         return ipoll;
00518 }
00519 
00520 void setPathCleanup(struct MU* m, unsigned cmd)
00521 {
00522         struct MailboxControl mbc = {};
00523 
00524         if (cmd){
00525                 mbc.mbc_flags = MBC_TO_MBXW(1)|MBC_TO_MBXR(1)|MBC_FLAGS_ONRELEASE;
00526                 mbc.mbxw[0] = cmd;
00527         }
00528 
00529         int rc = ioctl(m->fd, ACQ200_MBOX_IOWR, &mbc);
00530 
00531         if (rc != 0){
00532                 fprintf(stderr, "ioctl() failed: %d\n", rc);
00533         }
00534 }
00535 
00536 void acq200_setImask(int slot, const char* mask)
00537 {
00538         char knob[80];
00539         sprintf(knob, FMT_IMASK, slot);
00540         FILE *fp = fopen(knob, "w");
00541         if (fp == 0) {
00542                 perror(knob);
00543                 exit(errno);
00544         }
00545         if (fp){
00546                 fprintf(fp, "%s\n", mask? mask: "00000000");
00547         }
00548         fclose(fp);
00549 }
00550 
00551 void acq200_setImask(int slot, u32* mask)
00552 {
00553         char knob[80];
00554         sprintf(knob, FMT_IMASK, slot);
00555         FILE *fp = fopen(knob, "w");
00556         if (fp == 0) {
00557                 perror(knob);
00558                 exit(errno);
00559         }
00560         if (fp){
00561                 fprintf(fp, "0x%08x\n", mask? mask[0]: 0);
00562         }
00563         fclose(fp);
00564 }