LLC2_API
|
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 }