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 #include "local.h"
00040
00041
00042 #include <assert.h>
00043 #include "llif.h"
00044
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047
00048 #include <errno.h>
00049 #include <fcntl.h>
00050 #include <sys/ioctl.h>
00051 #include <sys/mman.h>
00052 #include <sys/stat.h>
00053 #include <sys/types.h>
00054 #include <stdio.h>
00055 #include <unistd.h>
00056
00057
00058 #include "acq32ioctl.h"
00059
00060
00061
00062
00063
00064 #ifndef dbg
00065 #define dbg(level, fmt, arg...) fprintf(stderr, fmt, ## arg)
00066 #endif
00067
00068 typedef volatile u32 r32;
00069
00070 struct MU {
00071 int fd;
00072 r32* mailboxes;
00073 u32 mailboxes_shadow[4];
00074 u32 mailboxes_lastwrite[4];
00075 r32 *inbound_q_port;
00076 r32 *outbound_q_port;
00077
00078 int poll_count;
00079 };
00080
00081 #define FNAME_FMT "/dev/acq32/acq32.%d."
00082 #define FNAME_FMT_MBOX FNAME_FMT "raw"
00083 #define FNAME_FMT_DMABUF FNAME_FMT "01" // don't ask - this is a convenience
00084
00085 #define FNAME_FMT_HOST FNAME_FMT "host"
00086
00087 #define FMT_SYS_PARAMS "/sys/module/acq200_hostdrv/parameters/"
00088 #define FMT_SYS_SLOTS FMT_SYS_PARAMS "slots"
00089
00090 #define FMT_SYS_DEV "/sys/class/acqX00/acq200.%d/device/"
00091 #define FMT_SYS_DEV_HOST_PA FMT_SYS_DEV "host_pa"
00092 #define FMT_SYS_DEV_HOST_LEN FMT_SYS_DEV "host_len"
00093
00094
00095 static int lookup_device_index(int slot)
00096 {
00097 static int mapping[16];
00098 static int valid;
00099 int rc;
00100
00101 if (!valid){
00102 char slotdef[128];
00103 int ii;
00104 FILE *fp;
00105
00106 fp = fopen(FMT_SYS_SLOTS, "r");
00107 if (!fp){
00108 fprintf(stderr, "Failed to open slot mapping:\"%s\"",
00109 FMT_SYS_SLOTS);
00110 exit(errno);
00111 }
00112
00113 for (ii = 0; ii < 16; ++ii){
00114 mapping[ii] = -1;
00115 }
00116 if (fgets(slotdef, 128, fp)){
00117 char *cp;
00118 for (cp = slotdef, ii = 0;
00119 ii < 16 && (cp = strtok(cp, ",")) != 0;
00120 cp = 0, ++ii){
00121
00122 int slot_num = atoi(cp);
00123 assert(IN_RANGE(slot_num, 0, 15));
00124 if (slot_num != 0){
00125 mapping[slot_num] = ii;
00126 }
00127 }
00128 }
00129 valid = 1;
00130 }
00131
00132 rc = mapping[slot];
00133 if (rc == -1){
00134 fprintf(stderr, "No device found for slot %d", slot);
00135 exit(-1);
00136 }
00137 return rc;
00138 }
00139 static unsigned host_len(int iboard) {
00140 char fname[80];
00141 char line[80];
00142 char *my_line;
00143 unsigned len = 0;
00144 int rc;
00145
00146 sprintf(fname, FMT_SYS_DEV_HOST_LEN, lookup_device_index(iboard));
00147 FILE *fp = fopen(fname, "r");
00148 assert(fp);
00149
00150 my_line = fgets(line, sizeof(line), fp);
00151 assert(my_line);
00152
00153 rc = sscanf(my_line, "%u", &len);
00154 assert(rc);
00155 return len;
00156 }
00157 static unsigned host_pa(int iboard) {
00158 char fname[80];
00159 char line[80];
00160 char *my_line;
00161 unsigned pa = 0;
00162 int rc;
00163
00164 sprintf(fname, FMT_SYS_DEV_HOST_PA, lookup_device_index(iboard));
00165 FILE *fp = fopen(fname, "r");
00166 assert(fp);
00167
00168 my_line = fgets(line, sizeof(line), fp);
00169 assert(my_line);
00170
00171 rc = sscanf(my_line, "0x%x", &pa);
00172 assert(rc);
00173 return pa;
00174 }
00175
00176 int setMbox( struct MU* m, int ibox, u32 value )
00177
00178 {
00179 assert( IN_RANGE( ibox, 0, 3 ) );
00180
00181
00182 PRINTF(3)( "setMbox( %d, 0x%08x )\n", ibox, value );
00183 m->mailboxes[ibox] =
00184 m->mailboxes_shadow[ibox] =
00185 m->mailboxes_lastwrite[ibox] = value;
00186
00187 return 0;
00188 }
00189
00190 void showLastWrites( struct MU* m )
00191 {
00192 fprintf( stderr, "lastWrites()\n" );
00193 fprintf( stderr, "0x%08x 0x%08x 0x%08x 0x%08x\n",
00194 m->mailboxes_lastwrite[0],
00195 m->mailboxes_lastwrite[1],
00196 m->mailboxes_lastwrite[2],
00197 m->mailboxes_lastwrite[3] );
00198 }
00199 int setMboxBits( struct MU* m, int ibox, u32 bits_to_set )
00200 {
00201 assert( IN_RANGE( ibox, 0, 3 ) );
00202
00203 m->mailboxes[ibox] = m->mailboxes_shadow[ibox] |= bits_to_set;
00204 return 0;
00205 }
00206
00207 int clrMboxBits( struct MU* m, int ibox, u32 bits_to_clr )
00208 {
00209 assert( IN_RANGE( ibox, 0, 3 ) );
00210
00211 m->mailboxes[ibox] = m->mailboxes_shadow[ibox] &= ~bits_to_clr;
00212 return 0;
00213 }
00214
00215 int setMboxField( struct MU* m,
00216 int ibox, u32 field_mask, u32 field_value )
00217 {
00218 assert( IN_RANGE( ibox, 0, 3 ) );
00219
00220 m->mailboxes_shadow[ibox] &= ~field_mask;
00221 m->mailboxes_shadow[ibox] |= field_value;
00222 m->mailboxes[ibox] = m->mailboxes_shadow[ibox];
00223 return 0;
00224 }
00225
00226 u32 getMbox( struct MU* m, int ibox )
00227
00228 {
00229 u32 newval;
00230
00231 assert( IN_RANGE( ibox, 0, 3 ) );
00232
00233 newval = m->mailboxes[ibox];
00234
00235 if ( newval != m->mailboxes_shadow[ibox] ){
00236 PRINTF(4)( "getMbox( %d ) was:0x%08x now:0x%08x\n",
00237 ibox, m->mailboxes_shadow[ibox],
00238 newval);
00239 }
00240
00241 m->mailboxes_shadow[ibox] = newval;
00242 return m->mailboxes_shadow[ibox];
00243 }
00244
00245 u32 getMboxShadow(struct MU* m, int ibox)
00246 {
00247 assert( IN_RANGE( ibox, 0, 3 ) );
00248 return m->mailboxes_shadow[ibox];
00249 }
00250
00251 u32 pollMboxBits( struct MU* m, int ibox, u32 mask, u32 goal )
00252 {
00253 int ipoll = 0;
00254 u32 mbtemp;
00255
00256 while( ( (mbtemp = getMbox( m, ibox ))&mask ) == 0 ){
00257 if ( (++ipoll&0x3ffff) == 0 ){
00258 fprintf( stderr,
00259 "pollMboxBits() mask:0x%08x goal:0x%08x got:0x%08x\n",
00260 mask, goal, mbtemp );
00261 }
00262 }
00263
00264 PRINTF(4)( "pollMboxBits() returning 0x%08x\n", mbtemp );
00265 return mbtemp;
00266 }
00267
00268
00269 void setMboxPollcount(struct MU* m, int poll_count)
00270 {
00271 m->poll_count = poll_count;
00272 }
00273 int getMboxPollcount(struct MU* m)
00274 {
00275 return m->poll_count;
00276 }
00277
00278
00279 struct MU* mmapMbox( int iboard )
00280
00281 {
00282 char fname[80];
00283
00284 void* region;
00285 struct MU* m = malloc( sizeof(struct MU) );
00286 unsigned offset;
00287
00288 assert( m != 0 );
00289 assert( IN_RANGE( iboard, 1, 8 ) );
00290
00291 sprintf( fname, FNAME_FMT_MBOX, iboard );
00292
00293 if ( (m->fd = open( fname, O_RDWR )) < 0 ){
00294 fprintf( stderr, "mmap: failed to open device \"%s\" - ", fname );
00295 perror( "" );
00296 exit( 1 );
00297 }
00298
00299 region = mmap( NULL, 0x400, PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, 0 );
00300
00301 if ( region == (void*)-1 ){
00302 char errbuf[256];
00303 sprintf(errbuf, "%s %s", "mmap", fname);
00304 perror(errbuf);
00305 exit( 1 );
00306 }
00307
00308 #if 0
00309
00310
00311 if ( ioctl( m->fd, ACQ32_IOG_PCIREGS_OFFSET, &offset ) != 0 ){
00312 perror( "ioctl ACQ32_IOG_PCIREGS_OFFSET" );
00313 exit( 1 );
00314 }
00315 #else
00316 offset = 16;
00317 #endif
00318
00319 PRINTF(1)("mmap %p offset %d\n", region, offset);
00320 PRINTF(2)("data: %08x %08x %08x %08x\n",
00321 ((unsigned*)(region+offset))[0],
00322 ((unsigned*)(region+offset))[1],
00323 ((unsigned*)(region+offset))[2],
00324 ((unsigned*)(region+offset))[3] );
00325
00326 #ifndef __ACQ196__
00327 m->mailboxes = (r32*)((char*)region+offset+MAILBOX_0);
00328 #else
00329 m->mailboxes = (r32*)((char*)region+offset);
00330 m->inbound_q_port = (r32*)((char*)region+offset+0x30);
00331 m->outbound_q_port = (r32*)((char*)region+offset+0x34);
00332 #endif
00333 getMbox( m, 0 );
00334 getMbox( m, 1 );
00335 getMbox( m, 2 );
00336 getMbox( m, 3 );
00337
00338 return m;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 #define MAX_MAPPING 0x00100000 // 1MB is a handy # to play with
00353 #define MAX_SEG 0x00020000 // Linux maps 128k segments
00354
00355 #define MAX_SEGMENTS (MAX_MAPPING/MAX_SEG)
00356
00357 struct SegmentMap {
00358 int offset;
00359 int length;
00360 u32 physaddr;
00361 int pad;
00362 };
00363
00364
00365 struct DmaBuffer {
00366 u32* vaddr;
00367 int nbytes;
00368 struct SegmentMap seg_map[MAX_SEGMENTS];
00369 };
00370
00371 int getDmaBufferLen(struct DmaBuffer* buffer)
00372 {
00373 return buffer->nbytes;
00374 }
00375
00376 struct DmaBuffer* mmapDmaBuffer( int iboard, unsigned nbytes )
00377
00378
00379 {
00380 char fname[80];
00381 int fd_in;
00382 caddr_t* region;
00383 u32* phys_defs;
00384 int idef;
00385 u32 offset;
00386 int rc;
00387 struct DmaBuffer* d = malloc( sizeof( struct DmaBuffer ) );
00388
00389 PRINTF(1)("mmapDmaBuffer 01\n");
00390
00391 assert( d != 0 );
00392
00393 sprintf( fname, FNAME_FMT_DMABUF, iboard );
00394
00395
00396
00397 if ( (fd_in = open( fname, O_RDWR )) < 0 ){
00398 fprintf( stderr, "mmap: failed to open device \"%s\" - ", fname );
00399 perror( "" );
00400 exit( 1 );
00401 }
00402
00403
00404
00405
00406
00407 region = mmap( NULL, nbytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd_in, 0 );
00408
00409 if ( region == (caddr_t*)-1 ){
00410 perror( "mmap" );
00411 exit( 1 );
00412 }
00413
00414
00415
00416
00417
00418 PRINTF(3)( "region is %p\n", region );
00419
00420 rc = ioctl( fd_in, ACQ32_IOREAD_GETPHYSICAL, region );
00421
00422 if ( rc < 0 ){
00423 perror( "ioctl ACQ32_IOREAD_GETPHYSICAL failed" );
00424 exit( 1 );
00425 }
00426
00427
00428
00429
00430 phys_defs = (u32*)region;
00431
00432 for ( idef = 0, offset = 0; idef != MAX_SEGMENTS; idef += 1 ){
00433 if ( phys_defs[idef*2] == 0 ){
00434 PRINTF(3)( "quitting after %d segments\n", idef );
00435 break;
00436 }else{
00437 PRINTF(3)( "adding segment %d at offset 0x%08x phys 0x%08x"
00438 " len 0x%08x\n",
00439 idef, offset, phys_defs[idef*2], phys_defs[idef*2+1] );
00440 d->seg_map[idef].offset = offset;
00441 d->seg_map[idef].physaddr = phys_defs[idef*2];
00442 d->seg_map[idef].length = phys_defs[idef*2+1];
00443 offset += phys_defs[idef*2+1];
00444 }
00445 }
00446
00447 d->vaddr = (u32*)region;
00448 d->nbytes = nbytes;
00449 return d;
00450 }
00451
00452 u32 getBusAddr( struct DmaBuffer* d, u32 offset )
00453
00454
00455
00456 {
00457 int idef;
00458
00459 for ( idef = 0; idef != MAX_SEGMENTS; ++idef ){
00460 if ( offset >= d->seg_map[idef].offset &&
00461 offset < d->seg_map[idef].offset + d->seg_map[idef].length ){
00462 return d->seg_map[idef].physaddr + offset -
00463 d->seg_map[idef].offset;
00464 }
00465 }
00466
00467 return 0;
00468 }
00469
00470 u32* getVaddr( struct DmaBuffer* db, u32 offset )
00471 {
00472 if ( offset < db->nbytes ){
00473 PRINTF(4)( "getVaddr %p %d %p\n", db->vaddr, offset,
00474 &db->vaddr[offset/sizeof(u32)] );
00475
00476 return &db->vaddr[offset/sizeof(u32)];
00477 }else{
00478 return 0;
00479 }
00480 }
00481
00482 void acq32_enableInts( struct MU* mbx, unsigned mask )
00483 {
00484 if ( ioctl( mbx->fd, ACQ32_IOS_INTS_ENABLE, mask ) != 0 ){
00485 perror( "ioctl ACQ32_IOS_INTS_ENABLE" );
00486 exit( 1 );
00487 }
00488 }
00489 void acq32_maskInts( struct MU* mbx, unsigned mask )
00490 {
00491 if ( ioctl( mbx->fd, ACQ32_IOS_INTS_DISABLE, mask ) != 0 ){
00492 perror( "ioctl ACQ32_IOS_INTS_DISABLE" );
00493 exit( 1 );
00494 }
00495 }
00496
00497
00498
00499 struct DmaBuffer* mmapBigBuffer( int iboard, unsigned nbytes )
00500
00501
00502 {
00503 #define FN "mmapDmaBuffer() "
00504 char fname[80];
00505 int fd_in;
00506 caddr_t* region;
00507 struct DmaBuffer* d = malloc( sizeof( struct DmaBuffer ) );
00508
00509 assert( d != 0 );
00510
00511
00512
00513 sprintf(fname, FNAME_FMT_HOST, iboard );
00514
00515 PRINTF(1)(FN"01: open %s\n", fname);
00516
00517
00518
00519 if ( (fd_in = open( fname, O_RDWR )) < 0 ){
00520 fprintf(stderr, "mmap:failed to open device \"%s\" - ", fname);
00521 perror( "" );
00522 exit( 1 );
00523 }
00524
00525
00526
00527
00528 #ifdef __ACQ196__
00529 nbytes = host_len(iboard);
00530 PRINTF(1)(FN"ask for full bigbuf portion %x\n", nbytes);
00531 #endif
00532
00533 PRINTF(1)( FN"map at most %d bytes\n", nbytes );
00534
00535 region = mmap( NULL, nbytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd_in, 0 );
00536
00537 if ( region == (caddr_t*)-1 ){
00538 perror( "mmap" );
00539 exit( 1 );
00540 }
00541
00542
00543
00544
00545 d->seg_map[0].physaddr = host_pa(iboard);
00546 d->seg_map[0].offset = 0;
00547 d->seg_map[0].length = nbytes;
00548 d->vaddr = (u32*)region;
00549 d->nbytes = nbytes;
00550
00551 PRINTF(1)( FN "physaddr 0x%08x vaddr 0x%08x\n",
00552 d->seg_map[0].physaddr, (u32)d->vaddr );
00553
00554 return d;
00555 #undef FN
00556 }
00557
00558
00559 void mmapValidateDmaBuffer( struct MU* m, int nsamples )
00560 {
00561
00562 }
00563
00564 #define INITBUF_MARKER 0x1100c0de
00565
00566
00567
00568 static void udelay(int usecs)
00569
00570
00571
00572 {
00573 volatile int ii;
00574
00575 while(usecs--){
00576 for(ii = 0x10; --ii;){
00577 ;
00578 }
00579 }
00580 }
00581
00582 void hbPrimeBuffer(struct DmaBuffer *buf)
00583
00584 {
00585 int len = buf->nbytes - 0x100000;
00586
00587 assert(len > 0);
00588
00589 memset32(buf->vaddr, INITBUF_MARKER, len/sizeof(u32));
00590 }
00591
00592 void hbPrimePoll(struct DmaBuffer *buf, int offset, int sample_len)
00593 {
00594 int end32 = (offset + sample_len)/sizeof(u32);
00595 volatile u32* marker = &buf->vaddr[end32-2];
00596
00597 marker[0] = INITBUF_MARKER;
00598 marker[1] = INITBUF_MARKER;
00599 }
00600 int hbPoll(
00601 struct DmaBuffer *buf, int offset, int sample_len,
00602 volatile int *user_abort)
00603 {
00604 int end32 = (offset + sample_len)/sizeof(u32);
00605 volatile u32* marker = &buf->vaddr[end32-2];
00606 int ipoll = 1;
00607 int reported = 0;
00608
00609 while (marker[0] == INITBUF_MARKER && marker[1] == INITBUF_MARKER){
00610 udelay(1);
00611 ++ipoll;
00612 if (ipoll > 10000 && !reported){
00613 PRINTF(1)("hbPoll looking at %p\n", marker);
00614 reported = 1;
00615 }
00616 if (*user_abort){
00617 break;
00618 }
00619 }
00620
00621 return ipoll;
00622 }
00623
00624
00625 MFA mu_reserveOutbound(struct MU* mu)
00626 {
00627 return *mu->inbound_q_port;
00628 }
00629 int mu_putOutbound(struct MU* mu, MFA mfa)
00630
00631 {
00632 *mu->inbound_q_port = mfa;
00633 return 0;
00634 }
00635
00636
00637 MFA mu_getInbound(struct MU* mu)
00638 {
00639 return *mu->outbound_q_port;
00640 }
00641 int mu_returnInbound(struct MU* mu, MFA mfa)
00642 {
00643 *mu->outbound_q_port = mfa;
00644 return 0;
00645 }
00646