00001 /******************************************************************** 00002 00003 Name: esone.c 00004 Created by: Pierre-Andre Amaudruz & Stefan Ritt 00005 00006 Contents: CAMAC interface for ESONE standard using 00007 MCSTD (Midas Camac Standard) 00008 00009 $Id: esone.c 2759 2005-10-10 15:25:44Z ritt $ 00010 00011 \********************************************************************/ 00012 00013 /**dox***************************************************************/ 00014 /** @file esone.c 00015 The ESONE CAMAC standard call file 00016 */ 00017 00018 /**dox***************************************************************/ 00019 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00020 00021 #include <stdio.h> 00022 #include "mcstd.h" 00023 #include "esone.h" 00024 00025 #ifndef INLINE 00026 #if defined( _MSC_VER ) 00027 #define INLINE __inline 00028 #elif defined(__GNUC__) 00029 #define INLINE __inline__ 00030 #else 00031 #define INLINE 00032 #endif 00033 #endif 00034 00035 /*-- external representation added to MCSTD ------------------------*/ 00036 00037 INLINE void came_cn(int *ext, const int b, const int c, const int n, const int a) 00038 { 00039 *ext = (b << 24 | (c << 16) | (n << 8) | a); 00040 } 00041 00042 /*------------------------------------------------------------------*/ 00043 INLINE void came_ext(const int ext, int *b, int *c, int *n, int *a) 00044 { 00045 *b = (ext >> 24) & 0x7; 00046 *c = (ext >> 16) & 0x7; 00047 *n = (ext >> 8) & 0x1f; 00048 *a = (ext >> 0) & 0xf; 00049 } 00050 00051 /********************************************************************* 00052 * ESONE functions * 00053 *********************************************************************/ 00054 00055 /**dox***************************************************************/ 00056 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 00057 00058 /********************************************************************/ 00059 /** 00060 CAMAC initialization 00061 00062 CAMAC initialization must be called before any other ESONE 00063 subroutine call. 00064 00065 @return void 00066 */ 00067 INLINE void ccinit(void) 00068 { 00069 cam_init(); 00070 } 00071 00072 /********************************************************************/ 00073 /** 00074 CAMAC initialization with return status 00075 00076 fccinit can be called instead of ccinit to determine if the 00077 initialization was successful 00078 00079 @return 1 for success, 0 for failure 00080 */ 00081 INLINE int fccinit(void) 00082 { 00083 if (cam_init() == SUCCESS) 00084 return 1; 00085 00086 return 0; 00087 } 00088 00089 /********************************************************************/ 00090 /** 00091 Control Declaration REGister. 00092 00093 Compose an external address from BCNA for later use. 00094 Accessing CAMAC through ext could be faster if the external address is 00095 memory mapped to the processor (hardware dependent). Some CAMAC controller 00096 do not have this option see @ref AppendixB. 00097 @param ext external address 00098 @param b branch number (0..7) 00099 @param c crate number (0..) 00100 @param n station number (0..30) 00101 @param a sub-address (0..15) 00102 @return void 00103 */ 00104 INLINE void cdreg(int *ext, const int b, const int c, const int n, const int a) 00105 { 00106 came_cn(ext, b, c, n, a); 00107 } 00108 00109 /********************************************************************/ 00110 /** 00111 Control Short Operation. 00112 00113 16 bit operation on a given external CAMAC address. 00114 00115 The range of the f is hardware dependent. The number indicated below are for 00116 standard ANSI/IEEE Std (758-1979) 00117 Execute cam16i for f<8, cam16o for f>15, camc_q for (f>7 or f>23) 00118 00119 @param f function code (0..31) 00120 @param ext external address 00121 @param d data word 00122 @param q Q response 00123 @return void 00124 */ 00125 INLINE void cssa(const int f, int ext, unsigned short *d, int *q) 00126 { 00127 int b, c, n, a, x; 00128 00129 if (f < 8) { 00130 /* read */ 00131 came_ext(ext, &b, &c, &n, &a); 00132 cam16i_q(c, n, a, f, d, &x, q); 00133 } else if (f > 15) { 00134 /* write */ 00135 came_ext(ext, &b, &c, &n, &a); 00136 cam16o_q(c, n, a, f, *d, &x, q); 00137 } else if ((f > 7) || (f > 23)) { 00138 /* command */ 00139 came_ext(ext, &b, &c, &n, &a); 00140 camc_q(c, n, a, f, q); 00141 } 00142 } 00143 00144 /********************************************************************/ 00145 /** 00146 Control Full Operation. 00147 00148 24 bit operation on a given external CAMAC address. 00149 00150 The range of the f is hardware dependent. The number indicated below are for 00151 standard ANSI/IEEE Std (758-1979) 00152 Execute cam24i for f<8, cam24o for f>15, camc_q for (f>7 or f>23) 00153 00154 @param f function code (0..31) 00155 @param ext external address 00156 @param d data long word 00157 @param q Q response 00158 @return void 00159 */ 00160 INLINE void cfsa(const int f, const int ext, unsigned long *d, int *q) 00161 { 00162 int b, c, n, a, x; 00163 00164 if (f < 8) { 00165 /* read */ 00166 came_ext(ext, &b, &c, &n, &a); 00167 cam24i_q(c, n, a, f, d, &x, q); 00168 } else if (f > 15) { 00169 /* write */ 00170 came_ext(ext, &b, &c, &n, &a); 00171 cam24o_q(c, n, a, f, *d, &x, q); 00172 } else if ((f > 7) || (f > 23)) { 00173 /* command */ 00174 came_ext(ext, &b, &c, &n, &a); 00175 camc_q(c, n, a, f, q); 00176 } 00177 } 00178 00179 /********************************************************************/ 00180 /** 00181 Control Crate Clear. 00182 00183 Generate Crate Clear function. Execute cam_crate_clear() 00184 00185 @param ext external address 00186 @return void 00187 */ 00188 INLINE void cccc(const int ext) 00189 { 00190 int b, c, n, a; 00191 00192 came_ext(ext, &b, &c, &n, &a); 00193 cam_crate_clear(c); 00194 } 00195 00196 /********************************************************************/ 00197 /** 00198 Control Crate Z. 00199 00200 Generate Dataway Initialize. Execute cam_crate_zinit() 00201 00202 @param ext external address 00203 @return void 00204 */ 00205 INLINE void cccz(const int ext) 00206 { 00207 int b, c, n, a; 00208 00209 came_ext(ext, &b, &c, &n, &a); 00210 cam_crate_zinit(c); 00211 } 00212 00213 /********************************************************************/ 00214 /** 00215 Control Crate I. 00216 00217 Set or Clear Dataway Inhibit, Execute cam_inhinit_set() /clear() 00218 00219 @param ext external address 00220 @param l action l=0 -> Clear I, l=1 -> Set I 00221 @return void 00222 */ 00223 INLINE void ccci(const int ext, int l) 00224 { 00225 int b, c, n, a; 00226 00227 came_ext(ext, &b, &c, &n, &a); 00228 if (l) 00229 cam_inhibit_set(c); 00230 else 00231 cam_inhibit_clear(c); 00232 } 00233 00234 /********************************************************************/ 00235 /** 00236 Test Crate I. 00237 00238 Test Crate Inhibit, Execute cam_inhibit_test() 00239 00240 @param ext external address 00241 @param l action l=0 -> Clear I, l=1 -> Set I 00242 @return void 00243 */ 00244 INLINE void ctci(const int ext, int *l) 00245 { 00246 int b, c, n, a; 00247 00248 came_ext(ext, &b, &c, &n, &a); 00249 *l = cam_inhibit_test(c); 00250 } 00251 00252 /********************************************************************/ 00253 /** 00254 Control Crate D. 00255 00256 Enable or Disable Crate Demand. 00257 00258 @param ext external address 00259 @param l action l=0 -> Clear D, l=1 -> Set D 00260 @return void 00261 */ 00262 INLINE void cccd(const int ext, int l) 00263 { 00264 int b, c, n, a; 00265 00266 came_ext(ext, &b, &c, &n, &a); 00267 00268 if (l) 00269 cam_interrupt_enable(c); 00270 else 00271 cam_interrupt_disable(c); 00272 } 00273 00274 /********************************************************************/ 00275 /** 00276 Control Test Crate D. 00277 00278 Test Crate Demand. 00279 00280 @param ext external address 00281 @param l D cleared -> l=0, D set -> l=1 00282 @return void 00283 */ 00284 INLINE void ctcd(const int ext, int *l) 00285 { 00286 int b, c, n, a; 00287 00288 came_ext(ext, &b, &c, &n, &a); 00289 *l = cam_interrupt_test(c); 00290 } 00291 00292 /********************************************************************/ 00293 /** 00294 Control Declare LAM. 00295 00296 Declare LAM, Identical to cdreg. 00297 00298 @param lam external LAM address 00299 @param b branch number (0..7) 00300 @param c crate number (0..) 00301 @param n station number (0..30) 00302 @param a sub-address (0..15) 00303 @param inta implementation dependent 00304 @return void 00305 */ 00306 INLINE void cdlam(int *lam, const int b, const int c, const int n, 00307 const int a, const int inta[2]) 00308 { 00309 /* inta[2] ignored */ 00310 cdreg(lam, b, c, n, a); 00311 } 00312 00313 /********************************************************************/ 00314 /** 00315 Control Test Demand Present. 00316 00317 Test the LAM register. 00318 00319 @param ext external LAM register address 00320 @param l l !=0 if any LAM is set. 00321 @return void 00322 */ 00323 INLINE void ctgl(const int ext, int *l) 00324 { 00325 int b, c, n, a; 00326 unsigned long lam; 00327 00328 came_ext(ext, &b, &c, &n, &a); 00329 cam_lam_read(c, &lam); 00330 *l = (lam > 0); 00331 } 00332 00333 /********************************************************************/ 00334 /** 00335 Control Crate LAM. 00336 00337 Enable or Disable LAM. Execute F24 for disable, F26 for enable. 00338 00339 @param lam external address 00340 @param l action l=0 -> disable LAM , l=1 -> enable LAM 00341 @return void 00342 */ 00343 INLINE void cclm(const int lam, int l) 00344 { 00345 int b, c, n, a; 00346 00347 came_ext(lam, &b, &c, &n, &a); 00348 00349 if (l) 00350 camc(c, n, 0, 26); 00351 else 00352 camc(c, n, 0, 24); 00353 } 00354 00355 /********************************************************************/ 00356 /** 00357 Link LAM to service procedure 00358 00359 Link a specific service routine to a LAM. Since this routine 00360 is executed asynchronously, care must be taken on re-entrancy. 00361 00362 @param lam external address 00363 @param isr name of service procedure 00364 @return void 00365 */ 00366 INLINE void cclnk(const int lam, void (*isr) (void)) 00367 { 00368 int b, c, n, a; 00369 00370 came_ext(lam, &b, &c, &n, &a); 00371 00372 cam_interrupt_attach(c, n, isr); 00373 cam_lam_enable(c, n); 00374 cam_lam_clear(c, n); 00375 } 00376 00377 /********************************************************************/ 00378 /** 00379 Unlink LAM from service procedure 00380 00381 Performs complementary operation to cclnk. 00382 00383 @param lam external address 00384 @return void 00385 */ 00386 INLINE void cculk(const int lam) 00387 { 00388 int b, c, n, a; 00389 00390 came_ext(lam, &b, &c, &n, &a); 00391 cam_interrupt_detach(c, n); 00392 } 00393 00394 /********************************************************************/ 00395 /** 00396 Relink LAM 00397 00398 Re-enable LAM in the controller 00399 00400 @param lam external address 00401 @return void 00402 */ 00403 INLINE void ccrgl(const int lam) 00404 { 00405 int b, c, n, a; 00406 00407 came_ext(lam, &b, &c, &n, &a); 00408 00409 cam_lam_enable(c, n); 00410 cam_lam_clear(c, n); 00411 cam_interrupt_enable(c); 00412 } 00413 00414 /********************************************************************/ 00415 /** 00416 Control Clear LAM. 00417 00418 Clear the LAM of the station pointer by the lam address. 00419 00420 @param lam external address 00421 @return void 00422 */ 00423 INLINE void cclc(const int lam) 00424 { 00425 int b, c, n, a; 00426 00427 came_ext(lam, &b, &c, &n, &a); 00428 camc(c, n, 0, 10); 00429 } 00430 00431 /********************************************************************/ 00432 /** 00433 Test LAM. 00434 00435 Test the LAM of the station pointed by lam. Performs an F8 00436 00437 @param lam external address 00438 @param l No LAM-> l=0, LAM present-> l=1 00439 @return void 00440 */ 00441 INLINE void ctlm(const int lam, int *l) 00442 { 00443 int b, c, n, a; 00444 00445 came_ext(lam, &b, &c, &n, &a); 00446 camc_q(c, n, a, 8, l); 00447 } 00448 00449 /********************************************************************/ 00450 /** 00451 Control Full (24bit) word General Action. 00452 00453 @param f function code 00454 @param exta[] external address array 00455 @param intc[] data array 00456 @param qa[] Q response array 00457 @param cb[] control block array<br> 00458 cb[0] : number of function to perform<br> 00459 cb[1] : returned number of function performed 00460 @return void 00461 */ 00462 INLINE void cfga(int f[], int exta[], int intc[], int qa[], int cb[]) 00463 { 00464 int i; 00465 00466 for (i = 0; i < cb[0]; i++) 00467 cfsa(f[i], exta[i], (unsigned long *) (&(intc[i])), &(qa[i])); 00468 00469 cb[1] = cb[0]; 00470 } 00471 00472 /********************************************************************/ 00473 /** 00474 Control (16bit) word General Action. 00475 00476 @param f function code 00477 @param exta[] external address array 00478 @param intc[] data array 00479 @param qa[] Q response array 00480 @param cb[] control block array <br> 00481 cb[0] : number of function to perform<br> 00482 cb[1] : returned number of function performed 00483 @return void 00484 */ 00485 INLINE void csga(int f[], int exta[], int intc[], int qa[], int cb[]) 00486 { 00487 int i; 00488 00489 for (i = 0; i < cb[0]; i++) 00490 cssa(f[i], exta[i], (unsigned short *) (&(intc[i])), &(qa[i])); 00491 00492 cb[1] = cb[0]; 00493 } 00494 00495 /********************************************************************/ 00496 /** 00497 Control Full (24bit) Address Q scan. 00498 00499 Scan all sub-address while Q=1 from a0..a15 max from address extb[0] and store 00500 corresponding data in intc[]. If Q=0 while A<15 or A=15 then cross station boundary is applied 00501 (n-> n+1) and sub-address is reset (a=0). Perform action until either cb[0] action are performed 00502 or current external address exceeds extb[1]. 00503 00504 <b>implementation of cb[2] for LAM recognition is not implemented.</b> 00505 00506 @param f function code 00507 @param extb[] external address array<br> 00508 extb[0] : first valid external address <br> 00509 extb[1] : last valid external address 00510 @param intc[] data array 00511 @param cb[] control block array <br> 00512 cb[0] : number of function to perform <br> 00513 cb[1] : returned number of function performed 00514 @return void 00515 */ 00516 INLINE void cfmad(int f, int extb[], int intc[], int cb[]) 00517 { 00518 int j, count; 00519 int x, q, b, c, n, a; 00520 unsigned long exts, extc, exte; 00521 00522 exts = extb[0]; 00523 exte = extb[1]; 00524 count = cb[0]; 00525 j = 0; 00526 came_ext(exts, &b, &c, &n, &a); 00527 do { 00528 cam24i_q(c, n, a, f, (unsigned long *) &intc[j], &x, &q); 00529 if (q == 0) { 00530 a = 0; /* set subaddress to zero */ 00531 n++; /* select next slot */ 00532 j++; 00533 } else { 00534 a++; /* increment address */ 00535 ++cb[1]; /* increment tally count */ 00536 ++intc; /* next data array */ 00537 --count; 00538 } 00539 came_cn((int *) &extc, b, c, n, a); 00540 00541 if (extc > exte) 00542 count = 0; /* force exit */ 00543 00544 } while (count); 00545 } 00546 00547 /********************************************************************/ 00548 /** 00549 Control (16bit) Address Q scan. 00550 00551 Scan all sub-address while Q=1 from a0..a15 max from address extb[0] and store 00552 corresponding data in intc[]. If Q=0 while A<15 or A=15 then cross station boundary is applied 00553 (n-> n+1) and sub-address is reset (a=0). Perform action until either cb[0] action are performed 00554 or current external address exceeds extb[1]. 00555 00556 <b>implementation of cb[2] for LAM recognition is not implemented.</b> 00557 00558 @param f function code 00559 @param extb[] external address array<br> 00560 extb[0] : first valid external address <br> 00561 extb[1] : last valid external address 00562 @param intc[] data array 00563 @param cb[] control block array <br> 00564 cb[0] : number of function to perform <br> 00565 cb[1] : returned number of function performed 00566 @return void 00567 */ 00568 INLINE void csmad(int f, int extb[], int intc[], int cb[]) 00569 { 00570 int j, count; 00571 int x, q, b, c, n, a; 00572 unsigned long exts, extc, exte; 00573 00574 exts = extb[0]; 00575 exte = extb[1]; 00576 count = cb[0]; 00577 j = 0; 00578 came_ext(exts, &b, &c, &n, &a); 00579 do { 00580 cam16i_q(c, n, a, f, (unsigned short *) &intc[j], &x, &q); 00581 if (q == 0) { 00582 a = 0; /* set subaddress to zero */ 00583 n++; /* select next slot */ 00584 j++; 00585 } else { 00586 a++; /* increment address */ 00587 ++cb[1]; /* increment tally count */ 00588 ++intc; /* next data array */ 00589 --count; 00590 } 00591 came_cn((int *) &extc, b, c, n, a); 00592 00593 if (extc > exte) 00594 count = 0; /* force exit */ 00595 00596 } while (count); 00597 } 00598 00599 /********************************************************************/ 00600 /** 00601 Control Full (24bit) Block Repeat with Q-stop. 00602 00603 Execute function f on address ext with data intc[] while Q. 00604 00605 @param f function code 00606 @param ext external address array 00607 @param intc[] data array 00608 @param cb[] control block array <br> 00609 cb[0] : number of function to perform <br> 00610 cb[1] : returned number of function performed 00611 @return void 00612 */ 00613 INLINE void cfubc(const int f, int ext, int intc[], int cb[]) 00614 { 00615 int count, q; 00616 00617 count = cb[0]; 00618 do { 00619 cfsa(f, ext, (unsigned long *) intc, &q); 00620 if (q == 0) 00621 count = 0; /* stop on no q */ 00622 else { 00623 ++cb[1]; /* increment tally count */ 00624 ++intc; /* next data array */ 00625 --count; 00626 } 00627 } while (count); 00628 } 00629 00630 /********************************************************************/ 00631 /** 00632 Control (16bit) Block Repeat with Q-stop. 00633 00634 Execute function f on address ext with data intc[] while Q. 00635 00636 @param f function code 00637 @param ext external address array 00638 @param intc[] data array 00639 @param cb[] control block array <br> 00640 cb[0] : number of function to perform <br> 00641 cb[1] : returned number of function performed 00642 @return void 00643 */ 00644 INLINE void csubc(const int f, int ext, int intc[], int cb[]) 00645 { 00646 int count, q; 00647 00648 count = cb[0]; 00649 do { 00650 cssa(f, ext, (unsigned short *) intc, &q); 00651 if (q == 0) 00652 count = 0; /* stop on no q */ 00653 else { 00654 ++cb[1]; /* increment tally count */ 00655 ++intc; /* next data array */ 00656 --count; 00657 } 00658 } while (count); 00659 } 00660 00661 /********************************************************************/ 00662 /** 00663 Repeat Mode Block Transfer (24bit). 00664 00665 Execute function f on address ext with data intc[] if Q. 00666 If noQ keep current intc[] data. Repeat cb[0] times. 00667 00668 @param f function code 00669 @param ext external address array 00670 @param intc[] data array 00671 @param cb[] control block array <br> 00672 cb[0] : number of function to perform <br> 00673 cb[1] : returned number of function performed 00674 @return void 00675 */ 00676 INLINE void cfubr(const int f, int ext, int intc[], int cb[]) 00677 { 00678 int q, count; 00679 00680 count = cb[0]; 00681 do { 00682 do { 00683 cfsa(f, ext, (unsigned long *) intc, &q); 00684 } while (q == 0); 00685 00686 ++cb[1]; /* increment tally count */ 00687 ++intc; /* next data array */ 00688 --count; 00689 } while (count); 00690 } 00691 00692 /********************************************************************/ 00693 /** 00694 Repeat Mode Block Transfer (16bit). 00695 00696 Execute function f on address ext with data intc[] if Q. 00697 If noQ keep current intc[] data. Repeat cb[0] times. 00698 00699 @param f function code 00700 @param ext external address array 00701 @param intc[] data array 00702 @param cb[] control block array <br> 00703 cb[0] : number of function to perform <br> 00704 cb[1] : returned number of function performed 00705 @return void 00706 */ 00707 INLINE void csubr(const int f, int ext, int intc[], int cb[]) 00708 { 00709 int q, count; 00710 00711 count = cb[0]; 00712 do { 00713 do { 00714 cssa(f, ext, (unsigned short *) intc, &q); 00715 } while (q == 0); 00716 00717 ++cb[1]; /* increment tally count */ 00718 ++intc; /* next data array */ 00719 --count; 00720 } while (count); 00721 }