libedt.c

00001 /* #pragma ident "@(#)libedt.c  1.462 12/08/10 EDT" */
00002 
00003 #include "edtinc.h"
00004 
00005 #if defined(__linux__) || defined(__APPLE__)
00006 #include <unistd.h>
00007 #include <sys/mman.h>
00008 #include <sys/time.h>
00009 #include <sys/resource.h>
00010 #endif
00011 
00012 #include <stdlib.h>
00013 #include <ctype.h>
00014 
00015 #ifndef _NT_
00016 #include <sys/ioctl.h>
00017 #endif
00018 
00019 #ifdef VXWORKS
00020 #include "vmLib.h"
00021 #include "cacheLib.h"
00022 extern int sysGetVmPageSize();
00023 /* #include <strings.h>*/
00024 #include <string.h>
00025 #endif
00026 
00027 #ifdef _NT_
00028 
00029 #include <process.h>
00030 
00031 #else
00032 
00033 #ifndef VXWORKS
00034 #include <sys/errno.h>
00035 #endif
00036 
00037 #endif
00038 
00039 #ifdef __sun
00040 #include <thread.h>
00041 #endif
00042 #ifdef __sun
00043 #include <sys/mman.h>
00044 #endif
00045 #ifdef __sun
00046 #include <sys/priocntl.h>
00047 #include <sys/rtpriocntl.h>
00048 #include <sys/tspriocntl.h>
00049 #endif
00050 
00051 #if defined(_NT_)
00052 #include <process.h>
00053 #elif defined(__sun) || defined(__linux__) || defined(__APPLE__)
00054 #include <sys/wait.h>
00055 #endif
00056 
00057 
00058 #ifndef PAGE_SHIFT
00059 #define PAGE_SHIFT (12)
00060 #endif
00061 
00062 #ifndef PAGE_SIZE
00063 #define PAGE_SIZE (1UL << PAGE_SHIFT)
00064 #endif
00065 
00066 #ifndef PAGE_MASK
00067 #define PAGE_MASK (PAGE_SIZE-1)
00068 #endif
00069 
00070 
00071 /*
00072 * EDT Library
00073 *
00074 * Copyright (c) 1998, 2005 by Engineering Design Team, Inc.
00075 *
00076 * DESCRIPTION Provides a 'C' language   interface to the EDT PCI DMA cards
00077 * to simplify the       ring buffer method of reading data.
00078 *
00079 * All routines access a specific device, whose handle is created and returned
00080 * by    the edt_open() routine.
00081 *
00082 */
00083 
00084 /* support for dmy device */
00085 static u_int dmy_started = 0 ;
00086 
00087 
00088 int dump_reg_access = 0;
00089 
00090 
00091 static u_char *intfc_dump = 0;
00092 static u_char *base_dump = 0;
00093 static u_char *dma_reg_dump = 0;
00094 
00095 static int get_xref_info_params(char *str, char *fpga, char *sn, char *mtype, char *moffs, char *mnum, char *desc, char *rsvd1, char *rsvd2);
00096 static int isdigit_str(char *s);
00097 
00098 int dump_ir_access = 0;
00099 
00100 void edt_set_dump_reg_access(int on)
00101 
00102 {
00103     if (intfc_dump == NULL)
00104     {
00105         intfc_dump = (u_char *) calloc(256,1);
00106         base_dump = (u_char *) calloc(256,1);
00107         dma_reg_dump = (u_char *) calloc(256,1);
00108     }
00109 
00110     dump_reg_access = on;
00111 
00112 }
00113 
00114 int edt_get_dump_reg_access()
00115 
00116 {
00117     return dump_reg_access;
00118 }
00119 
00120 void edt_set_dump_ir_access(u_int on)
00121 
00122 {
00123     dump_ir_access = on;
00124     if (on)
00125         edt_set_dump_reg_access(on);
00126 
00127 }
00128 
00129 void edt_set_dump_reg_address(u_int reglow, u_int n, u_int on)
00130 
00131 {
00132     int type = (reglow >> 16) & 0xf;
00133     u_int i;
00134     u_int start = reglow & 0xff;
00135     u_int nmax;
00136 
00137     if (type == 3)
00138         nmax = 8;
00139     else
00140         nmax = 256;
00141 
00142     if (start + n > nmax-1)
00143         n = nmax-start;
00144 
00145     if (intfc_dump == NULL)
00146         edt_set_dump_reg_access(TRUE);
00147 
00148     switch(type)
00149     {
00150 
00151     case 0:
00152         for (i=start; i< start+n;i++)
00153             base_dump[i] = on;
00154 
00155         break;
00156 
00157     case 1:
00158         for (i=start; i< start+n;i++)
00159             intfc_dump[i] = on;
00160 
00161         break;
00162 
00163     case 3:
00164         if (n > 8)
00165             n = 8;
00166 
00167         for (i=start; i< start+n;i++)
00168             dma_reg_dump[i] = on;
00169 
00170         break;
00171 
00172     }
00173 
00174 }
00175 
00176 u_char
00177 is_reg_dumpable(u_int regvalue)
00178 
00179 {
00180     int type = EDT_REG_TYPE(regvalue);
00181 
00182     int offset = regvalue & 0xff;
00183     int class = EDT_REG_CLASS(regvalue);
00184 
00185     if (class == 1)
00186         return dump_ir_access;
00187 
00188     switch(type)
00189     {
00190     case 0:
00191         return base_dump[offset];
00192     case 1:
00193         return intfc_dump[offset];
00194     case 3:
00195         return dma_reg_dump[offset];
00196 
00197     }
00198 
00199     return 0;
00200 }
00201 
00202 void
00203 edt_setenv_reg_dump(const char *s)
00204 
00205 {
00206 char test[128];
00207 int low;
00208  int high;
00209 size_t index;
00210 int range=0;
00211 int in_number=0;
00212 int tindex=0;
00213 
00214 for (index=0;index<strlen(s)+1;index++)
00215 {
00216     switch(s[index]) {
00217         case '0':
00218         case '1':
00219         case '2':
00220         case '3':
00221         case '5':
00222         case '6':
00223         case '7':
00224         case '8':
00225         case '9':
00226         case 'A':
00227         case 'B':
00228         case 'C':
00229         case 'D':
00230         case 'E':
00231         case 'F':
00232         case 'a':
00233         case 'b':
00234         case 'c':
00235         case 'd':
00236         case 'e':
00237         case 'f':
00238             in_number=1;
00239             test[tindex++]=s[index];
00240         break;
00241 
00242         case ':':
00243         case ' ':
00244         case 0:
00245 
00246         if (in_number)
00247         {
00248             test[tindex] = 0;
00249             if (range)
00250                 high=strtol(test,NULL,16);
00251             else
00252                 low=strtol(test,NULL,16);
00253             if (range)
00254                 edt_set_dump_reg_address(low | INTFC_BYTE,(high-low+1),1);
00255              else
00256                 edt_set_dump_reg_address(low | INTFC_BYTE,1,1);
00257             range=0;
00258             in_number=0;
00259             tindex=0;
00260         }
00261         break;
00262         case '-':
00263         if (in_number)
00264         {
00265                 test[tindex] = 0;
00266                 low=strtol(test,NULL,16);
00267                 range=1;
00268                 in_number=0;
00269                 tindex=0;
00270         }
00271         break;
00272     }
00273 }
00274 }
00275 
00276 #ifndef _NT_
00277 
00278 extern int errno;
00279 
00280 static void
00281 edt_set_errno(int val)
00282 
00283 {
00284     errno = val;
00285 }
00286 
00287 #else
00288 
00289 #define edt_set_errno(val)
00290 
00291 #endif
00292 
00293 
00294 
00295 int edt_clear_wait_status(EdtDev *edt_p);
00296 
00297 #ifndef SECTOR_SIZE
00298 #define SECTOR_SIZE 512
00299 #endif
00300 
00301 #ifndef PAGESIZE
00302 #define PAGESIZE 4096
00303 #endif
00304 
00305 #define DEFAULT_BUFFER_GRANULARITY PAGESIZE
00306 #define MINHEADERSIZE SECTOR_SIZE
00307 /* shorthand debug level */
00308 #define EDTDEBUG EDTLIB_MSG_INFO_2
00309 #define EDTFATAL EDTLIB_MSG_FATAL
00310 #define EDTWARN EDTLIB_MSG_WARNING
00311 
00312 #if defined(__APPLE__)
00313 void *edt_mac_open(char *classname, int unit, int channel);
00314 void *edt_mac_ioctl(void *dataPort, int code, void *eis);
00315 #endif
00316 
00317 #ifdef _NT_
00318 static u_int WINAPI
00319 edt_wait_event_thread(void *);
00320 
00321 int
00322 edt_get_kernel_event(EdtDev *edt_p, int event_num);
00323 static
00324 void
00325 edt_clear_event_func(EdtEventHandler * p);
00326 
00327 #else
00328 #ifndef VXWORKS
00329 static void *
00330 edt_wait_event_thread(void *);
00331 #endif
00332 
00333 #endif
00334 
00335 #ifndef VXWORKS
00336 static char *BaseEventNames[] =
00337 {
00338     NULL,
00339     EDT_EODMA_EVENT_NAME,
00340     EDT_BUF_EVENT_NAME,
00341     EDT_STAT_EVENT_NAME,
00342     EDT_P16D_DINT_EVENT_NAME,
00343     EDT_P11W_ATTN_EVENT_NAME,
00344     EDT_P11W_CNT_EVENT_NAME,
00345     EDT_PDV_ACQUIRE_EVENT_NAME,
00346     EDT_EVENT_PCD_STAT1_NAME,
00347     EDT_EVENT_PCD_STAT2_NAME,
00348     EDT_EVENT_PCD_STAT3_NAME,
00349     EDT_EVENT_PCD_STAT4_NAME,
00350     EDT_PDV_STROBE_EVENT_NAME,
00351     EDT_EVENT_P53B_SRQ_NAME,
00352     EDT_EVENT_P53B_INTERVAL_NAME,
00353     EDT_EVENT_P53B_MODECODE_NAME,
00354     EDT_EVENT_P53B_DONE_NAME,
00355     EDT_PDV_EVENT_FVAL_NAME,
00356     EDT_PDV_EVENT_TRIGINT_NAME,
00357     EDT_EVENT_TEMP_NAME,
00358     NULL
00359 };
00360 #endif
00361 
00362 #ifdef USB
00363 
00371 u_int
00372 usb_reg_read (EdtDev *edt_p, u_int desc)
00373 {
00374     int i, addr;
00375     u_int retval = 0 ;
00376     unsigned char setup[3];
00377     unsigned char buf[5];
00378     int bytes;
00379 
00380     if (usb_claim_interface(edt_p->usb_p, 0) < 0)
00381     {
00382         edt_set_errno(EBUSY); ;
00383         return 0 ;
00384     }
00385 
00386     addr = EDT_REG_ADDR(desc) ;
00387 
00388     for (i = 0; i < EDT_REG_SIZE(desc); i++)
00389     {
00390         setup[0] = 0x03 ;
00391         setup[1] = addr ;
00392 
00393         /* Send setup bytes */
00394         if ((usb_bulk_write(edt_p->usb_p, 0x01, setup, 2,
00395             edt_p->usb_rtimeout)) < 0)
00396         {
00397             usb_release_interface(edt_p->usb_p, 0);
00398             edt_set_errno(EINVAL); ;
00399             return 0 ;
00400         }
00401 
00402         /* Read back setup bytes to verify */
00403         bytes = usb_bulk_read(edt_p->usb_p, 0x81, buf, 1, edt_p->usb_rtimeout);
00404 
00405         if (bytes < 1)
00406         {
00407             extern int errno ;
00408             usb_release_interface(edt_p->usb_p, 0);
00409             edt_set_errno(EINVAL); ;
00410             return 0 ;
00411         }
00412 
00413         ++addr ;
00414         retval |= ((u_int) buf[0] << (i * 8)) ;
00415     }
00416 
00417     usb_release_interface(edt_p->usb_p, 0);
00418 
00419     return retval ;
00420 }
00421 
00429 void
00430 usb_reg_write(EdtDev *edt_p, u_int desc, u_int value)
00431 {
00432     int i, addr, size;
00433     unsigned char setup[4];
00434     unsigned char buf[4];
00435 
00436     if (usb_claim_interface(edt_p->usb_p, 0) < 0)
00437     {
00438         edt_set_errno(EBUSY); ;
00439         return ;
00440     }
00441 
00442     addr = EDT_REG_ADDR(desc) ;
00443 
00444     for (i = 0; i < EDT_REG_SIZE(desc); i++)
00445     {
00446         if (EDT_REG_TYPE(desc) == REMOTE_USB_TYPE)
00447         {
00448             setup[0] = 0x04;
00449             setup[1] = addr ;
00450             setup[2] = value & 0xff ;
00451             size = 3 ;
00452         }
00453         else if (EDT_REG_TYPE(desc) == LOCAL_USB_TYPE)
00454         {
00455             setup[0] = 0x01;
00456             setup[1] = value & 0xff ;
00457             size = 2 ;
00458         }
00459 
00460         /* Send setup bytes */
00461         if ((usb_bulk_write(edt_p->usb_p, 0x01, setup, size,
00462             edt_p->usb_wtimeout)) < 0)
00463         {
00464             usb_release_interface(edt_p->usb_p, 0);
00465             edt_set_errno(EINVAL); ;
00466             return ;
00467         }
00468 
00469         addr++ ;
00470         value >>= 8 ;
00471     }
00472 
00473     usb_release_interface(edt_p->usb_p, 0);
00474 }
00475 
00476 
00477 /*
00478 * find the EDT USB board attached
00479 */
00480 struct usb_device *edt_find_usb_board(int unit)
00481 {
00482     struct usb_bus *p;
00483     struct usb_device *q;
00484 
00485     for (p = usb_busses; p; p = p->next)
00486     {
00487         q = p->devices;
00488         while(q)
00489         {
00490             if ((q->descriptor.idVendor==0x04b4) &&
00491                 (q->descriptor.idProduct=0x8613))
00492                 return q;
00493             else
00494                 q = q->next;
00495         }
00496     }
00497 
00498     return NULL;
00499 }
00500 #endif /* USB */
00501 
00502 
00503 static int edt_parse_devname(EdtDev *edt_p, char *edt_devname, int unit, int channel);
00504 
00505 EdtDev * edt_open_device_struct(EdtDev *edt_p,
00506                            const char *device_name,
00507                            int unit, int channel,
00508                            int verbose)
00509 
00510 {
00511 
00512     static char *debug_env = NULL;
00513     u_int   dmy;
00514     int edt_debug;
00515     static char *debug_file = NULL;
00516     int level;
00517 
00518     if ((debug_env == NULL)
00519         && ((debug_env = (char *) getenv("EDTDEBUG")) != NULL)
00520         && *debug_env != '0')
00521     {
00522         edt_debug = atoi(debug_env);
00523         level = edt_msg_default_level();
00524         if (edt_debug > 0)
00525         {
00526             level |= EDTLIB_MSG_INFO_1;
00527             level |= EDTLIB_MSG_INFO_2;
00528         }
00529         edt_msg_set_level(edt_msg_default_handle(), level);
00530 
00531         if ((debug_file == NULL)
00532             && ((debug_file = (char *) getenv("EDTDEBUGFILE")) != NULL)
00533             && *debug_file != '0')
00534         {
00535             edt_msg_set_name(edt_msg_default_handle(), debug_file);
00536         }
00537 
00538         edt_msg(EDTDEBUG, "environment DEBUG set to %d: enabling debug in edtlib\n", edt_debug);
00539     }
00540 
00541     if(verbose)
00542         edt_msg(EDTDEBUG, "edt_open_device(%s, %d)\n", device_name, unit);
00543 
00544     if ((strncmp(device_name, "dmy", 3) == 0) || (strncmp(device_name, "DMY", 3) == 0))
00545         edt_p->devid = DMY_ID;
00546 #ifdef USB
00547     else if (strncasecmp(device_name, "usb", 3) == 0)
00548         edt_p->devtype = USB_ID; /* Set until true ID retrieved from device */
00549 #endif
00550 
00551 
00552     if (edt_parse_devname(edt_p, (char *) device_name, unit, channel) != 0)
00553     {
00554         edt_msg(EDTFATAL, "Illegal EDT device name (edt_open_device):  %s\n", device_name);
00555         return NULL;
00556     }
00557 
00558     edt_p->unit_no = unit;
00559     edt_p->channel_no = channel;
00560 
00561 #ifdef USB
00562     if (edt_p->devtype == USB_ID)
00563     {
00564         struct usb_device *current_device = NULL;
00565 
00566         usb_init();
00567         usb_find_busses();
00568         usb_find_devices();
00569 
00570         current_device = edt_find_usb_board(unit);
00571 
00572         if(current_device==NULL)
00573         {
00574             edt_set_errno(ENODEV); ;
00575             return NULL;
00576         }
00577 
00578         edt_p->usb_p = usb_open(current_device);
00579 
00580         /*
00581         * The following assume that large buffer reads occur
00582         * on endpoints 82, 84, 86, and 88.  82 is channel 2,
00583         * 84 channel 1, etc.  Large buffer writes occur on
00584         * endpoints 2, 4, 6, and 8.
00585         */
00586         edt_p->usb_bulk_read_endpoint = 0x80 + (channel * 2) + 2 ;
00587         edt_p->usb_bulk_write_endpoint = (channel * 2) + 2 ;
00588 
00589     }
00590     else
00591 #endif
00592     {
00593 
00594 #ifdef _NT_
00595         edt_p->fd = CreateFile(edt_p->edt_devname,
00596             GENERIC_READ | GENERIC_WRITE,
00597             FILE_SHARE_READ | FILE_SHARE_WRITE,
00598             NULL,
00599             edt_p->devid == (DMY_ID) ? OPEN_ALWAYS
00600             : OPEN_EXISTING,
00601             FILE_ATTRIBUTE_NORMAL,
00602             NULL);
00603 
00604         if (edt_p->fd == INVALID_HANDLE_VALUE)
00605         {
00606             if (verbose)
00607                 edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", device_name);
00608 
00609             return (NULL);
00610         }
00611 #else
00612 #if defined (__APPLE__)
00613         /* dataPort = edt_mac_open("pcd",0) ;*/
00614         if (verbose)
00615             edt_msg(EDTWARN, "edt_devname %s unit %d channel %d\n",edt_p->edt_devname,unit,channel) ;
00616         if (edt_p->devid != DMY_ID)
00617         {
00618             int nchannels = 0;
00619             int dummy = 0;
00620   
00621             /* open channel zero so we can check max channel val before
00622              * attempting to open the actual channel.
00623              */ 
00624             if ((edt_p->fd = edt_mac_open(edt_p->edt_devname, unit, 0)) <= 0)
00625                 return NULL;
00626 
00627             edt_p->channel_no = 0;
00628             nchannels = edt_ioctl(edt_p, EDTG_MAXCHAN, &dummy); 
00629             if (channel < nchannels)
00630             {
00631                 edt_mac_close(edt_p->fd);
00632                 edt_p->channel_no = channel;
00633                 if ((edt_p->fd = edt_mac_open(edt_p->edt_devname, unit, channel)) <= 0 )
00634                 {
00635                     if (verbose)
00636                         edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00637                     return (NULL);
00638                 }
00639                 
00640                 edt_ioctl(edt_p, EDTG_DEVID, &edt_p->devid);
00641                 if (edt_is_pdv(edt_p))
00642                 {
00643                     if (strncmp(device_name, "pdv", 3) != 0)
00644                     {
00645                         if (verbose)
00646                             printf("%s not match for pdv\n",edt_p->edt_devname) ;
00647                         close(edt_p->fd) ;
00648                         return(NULL);
00649                     }
00650                 }
00651                 else if (edt_is_pcd(edt_p))
00652                 {
00653                     if (strncmp(device_name, "pcd", 3) != 0)
00654                     {
00655                         if (verbose)
00656                             printf("%s not match for pcd\n",edt_p->edt_devname) ;
00657                         close(edt_p->fd) ;
00658                        return(NULL);
00659                     }
00660                 }
00661             }
00662             else
00663             {
00664                 edt_msg(EDTWARN, "EDT %s open failed. Channel number %d is larger than max allowed %d\n", edt_p->edt_devname, channel, nchannels-1); 
00665                 return NULL;
00666             }
00667         }
00668         else
00669         {
00670             if (!edt_p->fd)
00671             {
00672                 if ((edt_p->fd = open(edt_p->edt_devname, O_RDWR|O_CREAT, 0666)) < 0 )
00673                 {
00674                     if (verbose)
00675                         edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00676                     return (NULL);
00677                 }
00678             }
00679             /* printf("skipping open with fd already open\n") ;*/
00680         }
00681 #else
00682 
00683         if ((edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666)) < 0 )
00684         {
00685             if (verbose)
00686                 edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00687             return (NULL);
00688         }
00689         /* make sure fd not carried across exec */
00690 #if defined( __linux__) || defined(__sun)
00691         fcntl(edt_p->fd, F_SETFD, FD_CLOEXEC);
00692 #endif
00693 
00694 #endif /* not apple */
00695 #endif
00696     }
00697 
00698 
00699 
00700     edt_msg(EDTDEBUG, "edt_open for %s unit %d succeeded\n", device_name, unit);
00701 
00702     if (edt_p->devid != DMY_ID)
00703     {
00704         edt_ioctl(edt_p, EDTG_DEVID, &edt_p->devid);
00705         edt_ioctl(edt_p, EDTS_RESETCOUNT, &dmy);
00706         dmy = edt_p->channel_no ;
00707         /* edt_ioctl(edt_p, EDTS_RESETSERIAL, &dmy); */
00708         edt_p->DMA_channels = edtdev_channels_from_type(edt_p);
00709 
00710 #ifdef _NT_
00711         edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
00712         edt_get_kernel_event(edt_p, EDT_EVENT_STAT);
00713         if (edt_p->devid == P53B_ID)
00714         {
00715             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_SRQ);
00716             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_INTERVAL);
00717             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_MODECODE);
00718             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_DONE);
00719         }
00720 #endif
00721     }
00722 
00723     edt_p->devtype = edt_devtype_from_id(edt_p->devid);
00724     edt_p->donecount = 0;
00725     edt_p->tmpbuf = 0;
00726     edt_p->dd_p = 0;
00727     edt_p->b_count = 0;
00728     edt_p->buffer_granularity = DEFAULT_BUFFER_GRANULARITY;
00729     edt_p->mezz.id = MEZZ_ID_UNKNOWN;
00730     edt_p->reg_fifo_io    = NULL;
00731     edt_p->reg_fifo_cnt   = NULL;
00732     edt_p->reg_fifo_ctl   = NULL;
00733     edt_p->reg_intfc_off  = NULL;
00734     edt_p->reg_intfc_dat  = NULL;
00735 
00736 
00737     return edt_p;
00738 }
00739 
00740 
00741 EdtDev *edt_open_device(const char *device_name, int unit, int channel, int verbose)
00742 
00743 {
00744     EdtDev *edt_p;
00745 
00746     if ((edt_p = (EdtDev *) calloc(1, sizeof(EdtDev))) == NULL)
00747     {
00748         char errstr[128];
00749         sprintf(errstr, "edtlib: malloc (%x) in edt_open failed\n", (int)sizeof(EdtDev));
00750         edt_msg_perror(EDTWARN, errstr);
00751         return (NULL);
00752     }
00753 
00754     return edt_open_device_struct(
00755         edt_p,
00756         device_name,
00757         unit, channel, verbose);
00758 }
00759 
00783 EdtDev *
00784 edt_open(const char *device_name, int unit)
00785 {
00786 
00787     return edt_open_device(device_name, unit, 0, 1);
00788 }
00789 
00790 
00804 EdtDev *
00805 edt_open_quiet(const char *device_name, int unit)
00806 {
00807     return edt_open_device(device_name, unit, 0, 0);
00808 }
00809 
00837 EdtDev *
00838 edt_open_channel(const char *device_name, int unit, int channel)
00839 {
00840     return edt_open_device(device_name, unit, channel, 1);
00841 }
00842 
00851 static int
00852 edt_parse_devname(EdtDev *edt_p, char *device_name, int unit, int channel)
00853 {
00854 
00855     char *format;
00856 
00857     char dev_string[512];
00858 
00859     if (!device_name)
00860         return -1;
00861 
00862     if (device_name[0] == '\\' || device_name[0] == '/')
00863     {
00864         strcpy(edt_p->edt_devname, device_name);
00865     }
00866     else if (edt_p->devid == DMY_ID)
00867     {
00868 #ifdef _NT_
00869         format = ".\\%s%d" ;
00870 #else
00871         format = "./%s%d" ;
00872 #endif
00873         (void) sprintf(edt_p->edt_devname, format, device_name, unit) ;
00874     }
00875     else
00876     {
00877         int i;
00878 
00879         strncpy(dev_string, device_name,511);
00880 
00881         for (i=0;dev_string[i]; i++)
00882             dev_string[i] = tolower(dev_string[i]);
00883 
00884 #ifdef _NT_
00885         dev_string[0] = toupper(dev_string[0]);
00886 #endif
00887 
00888 #if defined(__linux__)
00889         if (strcmp(dev_string, "pcd") == 0)
00890             strcpy(dev_string, "pcicd");
00891 #endif
00892 
00893 
00894 #ifdef _NT_
00895 
00896 #ifdef WDF_DRIVER
00897         if (channel > 0)
00898         {
00899             format = "\\\\.\\%s%d\\%d_%d";
00900         }
00901         else
00902         {
00903             format = "\\\\.\\%s%d\\%d_%d";
00904         }
00905         (void) sprintf(edt_p->edt_devname, format, dev_string, unit, unit, channel);
00906 #else
00907         if (channel > 0)
00908         {
00909             format = "\\\\.\\%s%d_%d";
00910         }
00911         else
00912         {
00913             format = "\\\\.\\%s%d";
00914         }
00915         (void) sprintf(edt_p->edt_devname, format, dev_string, unit, channel);
00916 
00917 
00918 #endif
00919 
00920 #else
00921         if (channel > 0)
00922         {
00923             format = "/dev/%s%d_%d";
00924         }
00925         else
00926         {
00927             format = "/dev/%s%d";
00928         }
00929         (void) sprintf(edt_p->edt_devname, format, dev_string, unit, channel);
00930 #endif
00931 
00932     }
00933     edt_msg(EDTDEBUG, "parse open to %s\n",edt_p->edt_devname) ;
00934 
00935     return 0;
00936 }
00937 
00948 int
00949 edt_close_device(EdtDev *edt_p)
00950 
00951 {
00952     u_int   i;
00953 #ifdef __sun
00954     EdtEventHandler *p;
00955 #endif
00956 
00957     edt_msg(EDTDEBUG, "edt_close()\n");
00958 
00959     for (i = 0; i < EDT_MAX_KERNEL_EVENTS; i++)
00960     {
00961 
00962 
00963 #ifdef __sun
00964         p = &edt_p->event_funcs[i];
00965         if (p->active)
00966         {
00967             p->active = 0;
00968 
00969             edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &i);
00970             edt_ioctl(p->owner, EDTS_CLR_EVENT, &i);
00971             sema_destroy(&p->sema_thread);
00972             thr_join(NULL, NULL, NULL);
00973         }
00974 #else
00975 #ifndef NO_PTHREAD
00976 
00977         edt_remove_event_func(edt_p, i);
00978 #endif
00979 #endif
00980     }
00981 
00982     if (edt_p->ring_buffers_configured)
00983         edt_disable_ring_buffers(edt_p);
00984 
00985     if (edt_p->fd)
00986     {
00987 #ifdef _NT_
00988         CloseHandle(edt_p->fd);
00989 #else
00990 #if defined (__APPLE__)
00991         edt_mac_close(edt_p->fd) ;
00992 #else
00993         close(edt_p->fd);
00994 #endif
00995 #endif
00996     }
00997 
00998     return 0;
00999 }
01000 
01001 int
01002 edt_close(EdtDev *edt_p)
01003 
01004 {
01005     edt_close_device(edt_p);
01006 
01007     free(edt_p);
01008 
01009     return 0;
01010 }
01011 
01012 #ifdef __sun
01013 
01014 typedef struct
01015 {
01016     uint_t  index;
01017     uint_t  writeflag;
01018     EdtDev *edt_p;
01019 }       thr_buf_args;
01020 
01021 static void *
01022 aio_thread(   void   *arg)
01023 
01024 {
01025     thr_buf_args *bufp = (thr_buf_args *) arg;
01026     int     ret;
01027     u_char *addr;
01028     uint_t  size;
01029     int     index;
01030     EdtDev *edt_p;
01031     extern int errno;
01032 
01033     edt_p = bufp->edt_p;
01034     index = bufp->index;
01035     addr = edt_p->ring_buffers[index];
01036     size = edt_p->rb_control[index].size;
01037 
01038     /*
01039     * Start a read which will block forever in this thread. aioread() does
01040     * the same thing but won't allow as much concurrency.  Lseek orders the
01041     * buffers inside the driver. also aioread has exit problems
01042     */
01043     edt_msg(EDTDEBUG, "start %s for %d addr %x\n",
01044         bufp->writeflag ? "write" : "read", index, (u_int) addr);
01045     edt_set_errno(0);;
01046     if (bufp->writeflag)
01047         ret = pwrite(edt_p->fd, addr, size, index * 512);
01048     else
01049         ret = pread(edt_p->fd, addr, size, index * 512);
01050     if (ret == -1)
01051     {
01052         char    errstr[128];
01053 
01054         if (errno)
01055             perror("pread");
01056         sprintf(errstr, "aio buffer %d at 0x%x", index, (u_int) addr);
01057         edt_msg_perror(EDTDEBUG, errstr);
01058         edt_msg_perror(EDTDEBUG, "aiothread\n");
01059     }
01060     edt_msg(EDTDEBUG, "end aiothread for %d\n", index);
01061     return (0);
01062 }
01063 
01064 #endif
01065 
01073 int
01074 edt_use_umem_lock(EdtDev *edt_p, u_int use_lock)
01075 {
01076     int ret = 0 ;
01077     if (edt_p->ring_buffers_configured)
01078     {
01079         printf("Can't change umem lock method when ring buffers active\n") ;
01080         return(1) ;
01081     }
01082     edt_msg(EDTDEBUG, "use umem lock %d ",use_lock) ;
01083     ret = edt_ioctl(edt_p, EDTS_UMEM_LOCK, &use_lock) ;
01084     edt_msg(EDTDEBUG, "returns %d\n",ret) ;
01085     if (ret)
01086     {
01087         edt_msg(EDTDEBUG,
01088             "Can't use Umem lock expect on solaris 2.8 or above\n") ;
01089     }
01090     else
01091     {
01092         edt_msg(EDTDEBUG,"Setting umem lock\n") ;
01093     }
01094     return(ret) ;
01095 }
01096 
01097 int
01098 edt_get_umem_lock(EdtDev *edt_p)
01099 {
01100     u_int using_lock ;
01101     edt_ioctl(edt_p, EDTG_UMEM_LOCK, &using_lock) ;
01102     edt_msg(EDTDEBUG,"Using lock returns %d\n",using_lock) ;
01103     return(using_lock) ;
01104 }
01105 
01116 int
01117 edt_get_numbufs(EdtDev *edt_p)
01118 
01119 {
01120     int nb = 0;
01121     edt_ioctl(edt_p, EDTG_NUMBUFS, &nb);
01122     return nb;
01123 }
01124 
01125 #ifdef __sun
01126 
01127 void
01128 edt_sun_lock_mem(EdtDev *edt_p, int index, int write_flag, EdtRingBuffer *pring)
01129 
01130 {
01131     int  using_lock = 0 ;
01132     int     count;
01133     thr_buf_args bufargs;
01134 
01135     using_lock = edt_get_umem_lock(edt_p) ;
01136 
01137     if (!using_lock)
01138     {
01139         bufargs.edt_p = edt_p;
01140         bufargs.index = index;
01141         bufargs.writeflag = write_flag;
01142 
01143         edt_msg(EDTDEBUG, "%d buffer thread\n", index);
01144         if (thr_create(NULL, 0,
01145             aio_thread,
01146             (void *) &bufargs, THR_BOUND,
01147             &pring->ring_tid))
01148         {
01149             edt_msg_perror(EDTWARN, "thr_create");
01150         }
01151         count = index + 1;
01152 
01153         edt_msg(EDTDEBUG, "Before WAITN");
01154         edt_ioctl(edt_p, EDTS_WAITN, &count);
01155         edt_msg(EDTDEBUG, "After WAITN");
01156     }
01157 }
01158 
01159 #endif
01160 
01161 /*
01162 * edt_configure_ring_buffer
01163 *
01164 * configures a single PCI Bus Configurable DMA Interface ring buffer.
01165 * 
01166 * @ref edt_configure_ring_buffers
01167 *
01168 * @param edt_p: device handle returned from edt_open
01169 * @param index: index of the buffer which buffer
01170 * @param bufsize: size of each buffer
01171 * @param nbufs: number of buffers
01172 * @param data_direction: indicates whether this connection is to be used for output or input
01173 *  @param  bufarray: array of pointers to application-allocated buffers (<b>deprecated</b> -- see note in /ref edt_configure_ring_buffers.
01174 *
01175 * @return 0 on success; -1 on error
01176 */
01177 
01178 static int
01179 edt_configure_ring_buffer(EdtDev * edt_p,
01180                           int index,
01181                           int bufsize,
01182                           int write_flag,
01183                           unsigned char *pdata)
01184 
01185 {
01186     buf_args sysargs;
01187     int allocated_size = bufsize;
01188     EdtRingBuffer *pring;
01189     int rc;
01190 
01191     if (index < 0 || index >= MAX_DMA_BUFFERS)
01192     {
01193         edt_set_errno(EINVAL);
01194 
01195         fprintf(stderr,
01196             "invalid buffer index %d < 0 or >= MAX_DMA_BUFFERS (%d)\n",
01197             index, MAX_DMA_BUFFERS);
01198         return -1;
01199     }
01200 
01201     pring = &edt_p->rb_control[index];
01202 
01203 
01204 
01205     pring->size = bufsize;
01206     pring->write_flag = write_flag;
01207 
01208     if (pdata || (edt_p->mmap_buffers))
01209     {
01210         pring->owned = FALSE;
01211         if (edt_p->fullbufsize)
01212             allocated_size = edt_p->fullbufsize;
01213     }
01214     else
01215     {
01216 #ifdef _NT_
01217         /* round up to full page for fast file access */
01218         if (allocated_size & (SECTOR_SIZE-1))
01219             allocated_size = ((allocated_size / SECTOR_SIZE)+1)* SECTOR_SIZE;
01220 #endif
01221         pdata =
01222             edt_alloc(allocated_size);
01223         pring->owned = TRUE;
01224     }
01225 
01226     pring->allocated_size = allocated_size;
01227 
01228     edt_p->ring_buffers[index] = pdata;
01229 
01230     sysargs.index = index;
01231     sysargs.writeflag = write_flag;
01232 #ifdef WIN32
01233     sysargs.addr = (uint64_t) (pdata);
01234 #else
01235     sysargs.addr = (uint64_t) ((unsigned long)pdata);
01236 #endif
01237 
01238     sysargs.size = bufsize;
01239 
01240     if (edt_p->mmap_buffers)
01241     {
01242         if ((rc = edt_ioctl(edt_p, EDTS_BUF_MMAP, &sysargs)) == 0)
01243         {
01244 #ifdef __sun
01245             edt_sun_lock_mem(edt_p, index, write_flag, pring);
01246 #endif
01247             return 0;
01248 
01249         }
01250         else
01251         {
01252             edt_msg(EDT_MSG_FATAL, "Unable to configure ring buffer\n");
01253             edt_msg(EDT_MSG_FATAL, "rc = %d\n", rc);
01254             return rc;
01255         }
01256     }
01257     else if (edt_ioctl(edt_p, EDTS_BUF, &sysargs) == 0)
01258     {
01259 #ifdef __sun
01260         edt_sun_lock_mem(edt_p, index, write_flag, pring);
01261 #endif
01262         return 0;
01263     }
01264     return (-1);
01265 }
01266 
01267 /*
01268 * Obsolete - was used as a workaround for edt_set_direction().
01269 * Still used in legacy code, so keep for compatibility.
01270 * TODO: needs to be made compatible with edt_p->mmap_buffers.
01271 */
01272 int
01273 edt_add_ring_buffer(EdtDev * edt_p,
01274                     unsigned int bufsize,
01275                     int write_flag,
01276                     void *pdata)
01277 {
01278 
01279     int     index = -1;
01280 
01281     int     i;
01282 
01283     if (!edt_p->mmap_buffers)
01284     {
01285 
01286         /* allocate a slot for the data */
01287 
01288         for (i = 0; i < MAX_DMA_BUFFERS; i++)
01289             if (edt_p->ring_buffers[i] == NULL)
01290                 break;
01291 
01292         if (i == MAX_DMA_BUFFERS)
01293             return -1;
01294 
01295         index = i;
01296 
01297         edt_p->ring_buffer_numbufs++;
01298 
01299         edt_ioctl(edt_p, EDTS_NUMBUFS, &edt_p->ring_buffer_numbufs);
01300 
01301         edt_configure_ring_buffer(edt_p, index, bufsize, write_flag, (u_char *) pdata);
01302     }
01303 
01304     return index;
01305 }
01306 
01307 
01308 /*
01309 * Obsolete - was used as a workaround for edt_set_direction(), but
01310 * no longer needed.  Still may show up in customer code, so keep.
01311 *
01312 * @return 0 on success, -1 on failure
01313 */
01314 int
01315 edt_configure_channel_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01316                                    int write_flag, unsigned char **bufarray)
01317 {
01318     return edt_configure_ring_buffers(edt_p, bufsize, numbufs,
01319         write_flag, bufarray) ;
01320 }
01321 
01322 static
01323 int edt_check_ring_buf_parms(EdtDev *edt_p, int numbufs, int bufsize,
01324                              unsigned char *pdata, unsigned char ** bufarray)
01325 
01326 {
01327 
01328     int maxbufs;
01329 
01330     if (!edt_p)
01331     {
01332         edt_msg_perror(EDTFATAL, "Invalid edt handle\n");
01333         return -1;
01334     }
01335 
01336 
01337     /* Odd number of bytes is illegal.  Mark & Chet Oct'2000 */
01338     if (bufsize & 0x01)
01339     {
01340         edt_set_errno(EINVAL); ;
01341 
01342         edt_msg_perror(EDTFATAL, "edt_configure_ring_buffers: bufsize must be an even number of bytes\n") ;
01343         return -1 ;
01344     }
01345     maxbufs = edt_get_max_buffers(edt_p) ;
01346     if (numbufs > maxbufs)
01347     {
01348 
01349         edt_set_errno(EINVAL); ;
01350 
01351         edt_msg_perror(EDTFATAL,
01352             "edt_configure_ring_buffers: number of bufs exceeds maximum\n") ;
01353         edt_msg_perror(EDTFATAL,
01354             "use edt_set_max_buffers to increase max\n") ;
01355         return -1 ;
01356     }
01357 
01358     edt_p->mmap_buffers = edt_get_mmap_buffers(edt_p);
01359 
01360     if (edt_p->mmap_buffers)
01361     {
01362         if (edt_p->buffer_granularity < PAGE_SIZE)
01363             edt_p->buffer_granularity = PAGE_SIZE;
01364 
01365     }
01366 
01367     if (edt_p->mmap_buffers && ((pdata != NULL) || (bufarray != NULL)))
01368     {
01369 
01370         edt_set_errno(EINVAL); ;
01371 
01372         edt_msg_perror(EDTFATAL,
01373             "edt_configure_ring_buffers: can't pass in user pointer when using mmap kernel buffers\n") ;
01374 
01375         return -1;
01376     }
01377 
01378     return 0;
01379 }
01380 
01381 caddr_t
01382 edt_reserve_kernel_mem(EdtDev *edt_p, u_int totalsize)
01383 
01384 {
01385     caddr_t p = NULL;
01386     buf_args sysargs;
01387 
01388     memset(&sysargs, 0, sizeof(sysargs));
01389 
01390     sysargs.size = totalsize;
01391 
01392     edt_ioctl(edt_p, EDTS_ALLOC_KBUFFER,&sysargs);
01393 
01394     p = (caddr_t) sysargs.addr;
01395 
01396     return p;
01397 
01398 }
01399 
01400 
01401 #define EDT_DMAMEM_OFFSET 0x10000000
01402 
01403 int
01404 edt_unmap_dmamem(EdtDev *edt_p)
01405 {
01406 
01407 #ifdef __linux__
01408 
01409     if (edt_p->base_buffer)
01410         munmap(edt_p->base_buffer, edt_p->totalsize);
01411 #elif defined(WIN32)
01412 
01413     caddr_t p = NULL;
01414     buf_args sysargs;
01415 
01416     memset(&sysargs, 0, sizeof(sysargs));
01417 
01418     sysargs.size = 0;
01419 
01420     edt_ioctl(edt_p, EDTS_ALLOC_KBUFFER,&sysargs);
01421 
01422 #endif
01423 
01424     return 0;
01425 }
01426 
01427 caddr_t
01428 edt_map_dmamem(EdtDev *edt_p)
01429 {
01430 
01431     caddr_t     ret = NULL;
01432 
01433 #ifdef __linux__
01434     int pagen = EDT_DMAMEM_OFFSET;
01435 
01436     ret = (caddr_t) mmap((caddr_t)0, edt_p->totalsize, PROT_READ|PROT_WRITE,
01437         MAP_SHARED, edt_p->fd, pagen);
01438 
01439 #elif defined(WIN32)
01440 
01441     /* This should already be allocated */
01442     ret = (caddr_t) edt_p->base_buffer;
01443 
01444 #endif
01445 
01446     if (ret == ((caddr_t)-1)) {
01447         perror("mmap call");
01448         return(0) ;
01449     }
01450 
01451     return(ret) ;
01452 }
01453 
01454 static int
01455 edt_allocate_ring_buffer_memory(EdtDev *edt_p, int bufsize, int numbufs, u_char *user_mem, u_char **buffers)
01456 
01457 {
01458 
01459     unsigned char * bp;
01460     int i;
01461 
01462     edt_p->fullbufsize = edt_get_total_bufsize(edt_p, bufsize, edt_p->header_size);
01463 
01464     edt_p->totalsize = edt_p->fullbufsize * numbufs;
01465 
01466 #ifdef __linux__
01467     if (edt_p->mmap_buffers)
01468     {
01469         /* don't allocate, we'll do that later */
01470 
01471 
01472         for (i=0;i<numbufs;i++)
01473             buffers[i] = NULL;
01474 
01475         return 0;
01476     }
01477 #endif
01478 
01479 
01480     if (edt_p->base_buffer)
01481     {
01482         edt_free(edt_p->base_buffer);
01483         edt_p->base_buffer = NULL;
01484     }
01485 
01486     if (user_mem)
01487     {
01488         bp = user_mem;
01489     }
01490     else
01491     {
01492 
01493 
01494         if (edt_p->mmap_buffers)
01495         {
01496             /* call routine to reserve */
01497             edt_p->ring_buffers_allocated = TRUE;
01498             edt_p->base_buffer = (u_char *) edt_reserve_kernel_mem(edt_p, edt_p->totalsize);
01499         }
01500         else
01501         {
01502             edt_p->ring_buffers_allocated = TRUE;
01503             edt_p->base_buffer = edt_alloc(edt_p->totalsize);
01504         }
01505 
01506         if (!edt_p->base_buffer)
01507         {
01508             edt_msg_perror(EDTFATAL, "Unable to allocate buffer memory\n");
01509             return -1;
01510         }
01511 
01512         bp = edt_p->base_buffer;
01513 
01514 
01515     }
01516 
01517     if (edt_p->header_offset < 0)
01518         bp += ((int) edt_p->header_size);
01519 
01520     for (i=0;i<numbufs;i++)
01521     {
01522         buffers[i] = bp;
01523         bp += edt_p->fullbufsize;
01524     }
01525 
01526 
01527     return 0;
01528 
01529 }
01530 
01531 
01578 static int
01579 edt_setup_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01580                        int write_flag, unsigned char *pdata, unsigned char **bufarray)
01581 {
01582     int     i;
01583     int rc;
01584 
01585     u_char *localbuf[MAX_DMA_BUFFERS];
01586     u_char ** buffers;
01587 
01588     buffers = (bufarray != NULL)?bufarray:localbuf;
01589 
01590     if ((rc = edt_check_ring_buf_parms(edt_p, numbufs, bufsize,  pdata, bufarray)) != 0)
01591         return rc;
01592 
01593     if (edt_p->ring_buffers_configured)
01594         edt_disable_ring_buffers(edt_p);
01595 
01596     edt_p->nextwbuf = 0;
01597     edt_p->donecount = 0;
01598     edt_p->ring_buffer_bufsize = bufsize;
01599     edt_p->ring_buffer_numbufs = numbufs;
01600 
01601     if (write_flag)
01602         edt_set_direction(edt_p, EDT_WRITE);
01603     else
01604         edt_set_direction(edt_p, EDT_READ);
01605 
01606     edt_p->write_flag = write_flag;
01607 
01608     edt_ioctl(edt_p, EDTS_NUMBUFS, &numbufs);
01609 
01610     if (bufarray == NULL)
01611     {
01612         if (edt_allocate_ring_buffer_memory(edt_p, bufsize, numbufs, pdata, buffers) != 0)
01613             return -1;
01614 
01615         edt_p->ring_buffers_allocated = !edt_p->mmap_buffers && (pdata == NULL);
01616     }
01617 
01618     for (i = 0; i < numbufs; i++)
01619     {
01620         if (edt_configure_ring_buffer(edt_p, i,
01621             bufsize,
01622             write_flag,
01623             buffers[i]) == 0)
01624         {
01625 
01626         }
01627         else
01628         {
01629             return -1;
01630         }
01631     }
01632 
01633     if (edt_p->mmap_buffers)
01634     {
01635         u_char *bp;
01636 
01637         edt_p->base_buffer = (u_char *) edt_map_dmamem(edt_p);
01638         bp = edt_p->base_buffer;
01639 
01640         for (i=0;i<numbufs;i++)
01641         {
01642             edt_p->ring_buffers[i] = bp;
01643             bp += edt_p->fullbufsize;
01644         }
01645 
01646         /* go ahead and page it in */
01647         bp = edt_p->base_buffer;
01648         for (i=0; i<(int)edt_p->totalsize;i += PAGE_SIZE)
01649             bp[i] = 0x5a;
01650 
01651 
01652     }
01653 
01654     edt_p->ring_buffers_configured = 1;
01655 
01656     return 0;
01657 }
01658 
01659 
01660 
01661 void edt_set_buffer_granularity(EdtDev *edt_p, u_int granularity)
01662 
01663 {
01664     edt_p->buffer_granularity = granularity;
01665 }
01666 
01667 
01678 int
01679 edt_get_total_bufsize(EdtDev *edt_p,
01680                       int bufsize,
01681                       int header_size)
01682 
01683 {
01684     int fullbufsize;
01685 
01686     fullbufsize = header_size + bufsize;
01687 
01688     if (edt_p->buffer_granularity)
01689         if (fullbufsize % edt_p->buffer_granularity)
01690             fullbufsize = ((fullbufsize / edt_p->buffer_granularity)+1)* edt_p->buffer_granularity;
01691 
01692     return fullbufsize;
01693 }
01694 
01695 
01741 int
01742 edt_configure_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01743                            int write_flag, unsigned char **bufarray)
01744 {
01745     return edt_setup_ring_buffers(edt_p, bufsize, numbufs, write_flag, NULL, bufarray);
01746 
01747 }
01748 
01759 int
01760 edt_configure_block_buffers_mem(EdtDev *edt_p,
01761                                 int bufsize,
01762                                 int numbufs,
01763                                 int write_flag,
01764                                 int header_size,
01765                                 int header_before,
01766                                 u_char *user_mem)
01767 
01768 {
01769 
01770     /* check for valid arguments */
01771     if (header_before && header_size)
01772     {
01773         if (header_size & (SECTOR_SIZE-1))
01774             header_size = ((header_size / SECTOR_SIZE)+1)* SECTOR_SIZE;
01775     }
01776 
01777 
01778     edt_p->header_size = header_size;
01779     edt_p->header_offset = (header_before)? -header_size : bufsize;
01780 
01781 
01782     return edt_setup_ring_buffers(edt_p, bufsize, numbufs, write_flag, user_mem, NULL);
01783 
01784 }
01785 
01786 
01865 int
01866 edt_configure_block_buffers(EdtDev *edt_p, int bufsize, int numbufs, int write_flag,
01867                             int header_size, int header_before)
01868 
01869 {
01870 
01871     return edt_configure_block_buffers_mem(edt_p,
01872         bufsize,
01873         numbufs,
01874         write_flag,
01875         header_size,
01876         header_before,
01877         NULL);
01878 
01879 }
01880 
01881 
01895 int
01896 edt_disable_ring_buffer(EdtDev *edt_p,
01897                         int whichone)
01898 
01899 {
01900     if (edt_p->ring_buffers[whichone])
01901     {
01902         /* detach buffer from DMA resources */
01903 
01904         edt_ioctl(edt_p, EDTS_FREEBUF, &whichone);
01905         edt_msg(EDTDEBUG, "free buf %d\n", whichone);
01906 
01907 #ifdef __sun
01908         {
01909             u_int using_lock ;
01910             using_lock = edt_get_umem_lock(edt_p) ;
01911             if (!using_lock)
01912             {
01913                 edt_msg(EDTDEBUG, "joining user buf %d tid %x\n",
01914                     whichone, edt_p->rb_control[whichone].ring_tid);
01915                 thr_join(edt_p->rb_control[whichone].ring_tid, NULL, NULL);
01916 
01917                 edt_msg(EDTDEBUG, "join user buf %d done\n", whichone);
01918             }
01919         }
01920 #endif
01921         /* free data pointer if we own it */
01922         if (edt_p->rb_control[whichone].owned)
01923         {
01924             edt_msg(EDTDEBUG, "free user buf %d\n", whichone);
01925             edt_free(edt_p->ring_buffers[whichone]);
01926         }
01927 
01928         edt_p->ring_buffers[whichone] = NULL;
01929 
01930     }
01931 #if defined(__hpux)
01932     {
01933         int pret ;
01934         pret = plock(UNLOCK) ;
01935     }
01936 #endif
01937 
01938     return 0;
01939 
01940 }
01941 
01942 
01954 int
01955 edt_disable_ring_buffers(EdtDev *edt_p)
01956 
01957 {
01958     int   i;
01959 
01960     /* for (i = 0; i < edt_p->ring_buffer_numbufs; i++)*/
01961     for (i = edt_p->ring_buffer_numbufs - 1; i >= 0 ; i--)
01962     {
01963         edt_disable_ring_buffer(edt_p,i);
01964     }
01965 
01966     edt_p->ring_buffers_configured = 0;
01967     edt_p->ring_buffers_allocated = 0;
01968 #if defined(__hpux)
01969     {
01970         int pret ;
01971         pret = plock(UNLOCK) ;
01972     }
01973 #elif defined(sgi)
01974     munlockall();
01975 #endif
01976 
01977     if (edt_p->base_buffer )
01978     {
01979 
01980         if (edt_p->mmap_buffers)
01981             edt_unmap_dmamem(edt_p);
01982         else
01983             edt_free(edt_p->base_buffer);
01984         edt_p->base_buffer = NULL;
01985     }
01986     /* Steve 1/11/01 to fix pdv_setsize bug */
01987     /* added NUMBUFS to fix dmaid issue 2/19/03 */
01988     {
01989         int one = 1;
01990         edt_p->ring_buffer_numbufs = 0;
01991         edt_ioctl(edt_p, EDTS_NUMBUFS, &one);
01992         edt_ioctl(edt_p, EDTS_CLEAR_DMAID, &one);
01993     }
01994 
01995     return 0;
01996 }
01997 
02012 int
02013 edt_start_buffers(EdtDev *edt_p, uint_t count)
02014 {
02015     if (edt_p->devid == DMY_ID && edt_p->dd_p)
02016         dmy_started += count ;
02017     edt_msg(EDTDEBUG, "edt_start_buffers %d\n", count);
02018     edt_ioctl(edt_p, EDTS_STARTBUF, &count);
02019     return 0;
02020 }
02021 
02022 
02023 int
02024 edt_lockoff(EdtDev * edt_p)
02025 {
02026     int     count = 0;
02027 
02028     edt_ioctl(edt_p, EDTS_STARTBUF, &count);
02029     return 0;
02030 }
02031 
02041 unsigned int
02042 edt_allocated_size(EdtDev *edt_p, int buffer)
02043 
02044 {
02045     if (buffer >= 0 && buffer < (int) edt_p->ring_buffer_numbufs)
02046     {
02047         return edt_p->rb_control[buffer].allocated_size;
02048     }
02049     return 0;
02050 }
02051 
02073 int
02074 edt_set_buffer(EdtDev *edt_p, uint_t bufnum)
02075 {
02076     edt_ioctl(edt_p, EDTS_SETBUF, &bufnum);
02077     edt_p->donecount = bufnum;
02078     if (edt_p->ring_buffer_numbufs)
02079         edt_p->nextwbuf = bufnum % edt_p->ring_buffer_numbufs;
02080     return 0;
02081 }
02082 
02103 int
02104 edt_read(EdtDev *edt_p, void   *buf, uint_t  size)
02105 {
02106     u_char *thisbuf;
02107 
02108 
02109     if (size & 0x01) /* Odd no of bytes illegal.  Mark & Chet Oct'2000 */
02110         -- size ;
02111 
02112 
02113     if (edt_p->last_direction != 1)
02114         edt_set_direction(edt_p, EDT_READ);
02115 
02116 
02117     if (edt_p->devid != DMY_ID)
02118     {
02119 
02120         if (edt_configure_ring_buffers(edt_p, size, 1, EDT_READ, NULL) != 0)
02121 
02122             return -1;
02123 
02124 
02125         edt_start_buffers(edt_p, 1) ;
02126 
02127 
02128         thisbuf = edt_wait_for_buffers(edt_p, 1);
02129 
02130 
02131         if (edt_timeouts(edt_p))
02132         {
02133             size = edt_get_timeout_count(edt_p);
02134             edt_msg(EDTDEBUG, "edt_read timeout with count %d\n", size);
02135         }
02136 
02137 
02138         memcpy(buf, thisbuf, size);
02139 
02140 
02141         edt_disable_ring_buffers(edt_p) ;
02142 
02143     }
02144 
02145 
02146     return (size);
02147 
02148 }
02149 
02173 int
02174 edt_write(EdtDev *edt_p, void   *buf, uint_t  size)
02175 {
02176     u_char **bufs;
02177 
02178 
02179     if (size & 0x01) /* Odd no of bytes illegal.  Mark & Chet Oct'2000 */
02180         -- size ;
02181 
02182     if (edt_p->last_direction != (EDT_WRITE+1))
02183         edt_set_direction(edt_p, EDT_WRITE);
02184 
02185     if (edt_p->devid != DMY_ID)
02186     {
02187 
02188         if (edt_configure_ring_buffers(edt_p, size, 1, EDT_WRITE, NULL) != 0)
02189 
02190             return -1;
02191 
02192 
02193         bufs = edt_buffer_addresses(edt_p);
02194 
02195 
02196         memcpy(bufs[0], buf, size);
02197 
02198 
02199         edt_start_buffers(edt_p, 1) ;
02200 
02201 
02202         (void) edt_wait_for_buffers(edt_p, 1);
02203 
02204 
02205         if (edt_timeouts(edt_p))
02206         {
02207             size = edt_get_timeout_count(edt_p);
02208             edt_msg(EDTDEBUG, "edt_read timeout with count %d\n", size);
02209         }
02210 
02211 
02212         edt_disable_ring_buffers(edt_p) ;
02213 
02214     }
02215 
02216 
02217     return (size);
02218 
02219 }
02220 
02221 int
02222 edt_write_pio(EdtDev *edt_p, u_char *buf, int size)
02223 
02224 {
02225     edt_sized_buffer argbuf;
02226 
02227     argbuf.size = size;
02228 
02229     memcpy(argbuf.data, buf, size);
02230 
02231     return edt_ioctl(edt_p, EDTS_WRITE_PIO, &argbuf);
02232 
02233 }
02234 
02235 
02248 unsigned char *
02249 edt_next_writebuf(EdtDev *edt_p)
02250 
02251 {
02252     unsigned char *buf_p;
02253 
02254     buf_p = edt_p->ring_buffers[edt_p->nextwbuf];
02255     edt_p->nextwbuf = ++edt_p->nextwbuf % edt_p->ring_buffer_numbufs;
02256     return buf_p;
02257 }
02258 
02273 uint_t
02274 edt_next_writebuf_index(EdtDev *edt_p)
02275 
02276 {
02277     uint_t ret = edt_p->nextwbuf;
02278     edt_p->nextwbuf = ++edt_p->nextwbuf % edt_p->ring_buffer_numbufs;
02279     return ret;
02280 }
02281 
02294 unsigned char **
02295 edt_buffer_addresses(EdtDev *edt_p)
02296 {
02297     return (edt_p->ring_buffers);
02298 }
02299 
02322 unsigned char *
02323 edt_wait_buffers_timed(EdtDev * edt_p, int count, u_int * timep)
02324 {
02325     u_char *ret;
02326 
02327     edt_msg(EDTDEBUG, "edt_wait_buffers_timed()\n");
02328 
02329     ret = edt_wait_for_buffers(edt_p, count);
02330     edt_get_timestamp(edt_p, timep, edt_p->donecount - 1);
02331 
02332     edt_msg(EDTDEBUG, "buf %d done %s (%x %x)\n",
02333         edt_p->donecount,
02334         edt_timestring(timep),
02335         timep[0], timep[1]);
02336 
02337     return (ret);
02338 }
02339 
02353 unsigned char *
02354 edt_last_buffer(EdtDev * edt_p)
02355 {
02356     u_char *ret;
02357     bufcnt_t     donecount;
02358     bufcnt_t     last_wait;
02359     int     delta;
02360 
02361     donecount = edt_done_count(edt_p);
02362     last_wait = edt_p->donecount;
02363 
02364     edt_msg(EDTDEBUG, "edt_last_buffer() last %d cur %d\n",
02365         last_wait, donecount);
02366 
02367     delta = donecount - last_wait;
02368 
02369     if (delta == 0)
02370         delta = 1;
02371 
02372     ret = edt_wait_for_buffers(edt_p, delta) ;
02373     return (ret);
02374 }
02375 
02397 unsigned char *
02398 edt_last_buffer_timed(EdtDev * edt_p, u_int * timep)
02399 {
02400     u_char *ret;
02401     bufcnt_t     donecount;
02402     bufcnt_t     last_wait;
02403     int     delta;
02404 
02405     donecount = edt_done_count(edt_p);
02406     last_wait = edt_p->donecount;
02407 
02408     edt_msg(EDTDEBUG, "edt_last_buffer_timed() last %d cur %d\n",
02409         last_wait, donecount);
02410 
02411     delta = donecount - last_wait;
02412 
02413     if (delta == 0)
02414         delta = 1;
02415 
02416     ret = edt_wait_buffers_timed(edt_p, delta, timep);
02417     return (ret);
02418 }
02419 
02420 char   *
02421 edt_timestring(u_int * timep)
02422 {
02423     static char timestr[100];
02424     struct tm *tm_p;
02425     time_t testtm ;
02426 
02427     /* timep is sec,nsec in two 32 bit ints */
02428     /* works when passed to localtime on 32 bit system, but not 64 */
02429     testtm = timep[0] ;
02430     tm_p = localtime(&testtm);
02431     timep++;
02432     sprintf(timestr, "%02d:%02d:%02d.%06d",
02433         tm_p->tm_hour,
02434         tm_p->tm_min,
02435         tm_p->tm_sec,
02436         *timep);
02437 
02438     return timestr;
02439 }
02440 
02458 int
02459 edt_do_timeout(EdtDev *edt_p)
02460 
02461 {
02462     int dummy;
02463 
02464     return edt_ioctl(edt_p,EDTS_DOTIMEOUT,&dummy);
02465 
02466 }
02467 
02481 int
02482 edt_inc_timeout(EdtDev *edt_p)
02483 {
02484     int dummy;
02485 
02486     return edt_ioctl(edt_p,EDTS_INCTIMEOUT,&dummy);
02487 
02488 }
02489 
02518 unsigned char *
02519 edt_wait_for_buffers(EdtDev * edt_p, int count)
02520 {
02521     int     bufnum;
02522     int     ret = 0;
02523     bufcnt_t tmpcnt = count ;
02524 #ifdef _NT_
02525     int timeoutval = edt_get_rtimeout(edt_p);
02526 #endif
02527 
02528     edt_msg(EDTDEBUG, "edt_wait_for_buffers(%d)\n", count);
02529 
02530     if (edt_p->ring_buffer_numbufs == 0)
02531     {
02532         edt_msg(EDTDEBUG, "wait for buffers called with 0 buffers\n");
02533         return (0);
02534     }
02535     tmpcnt += edt_p->donecount;
02536 
02537 #ifdef _NT_
02538 
02539     edt_p->last_wait_ret = EDT_WAIT_OK;
02540 
02541     if (edt_get_drivertype(edt_p) != EDT_WDM_DRIVER)
02542 
02543     {
02544         HANDLE event;
02545         int rc;
02546 
02547 
02548         if (!edt_p->event_funcs[EDT_EVENT_BUF].wait_event)
02549         {
02550             edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
02551         }
02552 
02553         event = edt_p->event_funcs[EDT_EVENT_BUF].wait_event;
02554 
02555         while (edt_done_count(edt_p) < tmpcnt)
02556         {
02557 
02558             /* wait for event */
02559 
02560             if (timeoutval == 0)
02561                 timeoutval = INFINITE;
02562 
02563             ret = EDT_WAIT_OK;
02564             edt_clear_wait_status(edt_p);
02565 
02566             rc = WaitForSingleObject(event, timeoutval);
02567 
02568             if (rc == WAIT_TIMEOUT)
02569             {
02570                 if (edt_get_timeout_ok(edt_p))
02571                 {
02572                     ret = EDT_WAIT_OK_TIMEOUT;
02573                 }
02574                 else
02575                 {
02576                     edt_msg(EDTDEBUG, "timeout...\n");
02577 
02578                     /* deal with timeout */
02579 
02580                     edt_do_timeout(edt_p);
02581                     ResetEvent(event) ;
02582                     ret = EDT_WAIT_TIMEOUT;
02583                 }
02584                 break;
02585             }
02586             else if (edt_had_user_dma_wakeup(edt_p))
02587             {
02588                 ret = EDT_WAIT_USER_WAKEUP;
02589                 break;
02590 
02591             }
02592         }
02593     }
02594     else
02595     {
02596         ret = edt_ioctl(edt_p, EDTS_WAITBUF, &tmpcnt);
02597     }
02598 #else
02599 
02600     ret = edt_ioctl(edt_p, EDTS_WAITBUF, &tmpcnt);
02601     ret = edt_get_wait_status(edt_p);
02602 
02603 #endif
02604 
02605 
02606     edt_msg(EDTDEBUG, "edt_wait_for_buffers %d done ret = %d\n", count,
02607         ret);
02608     if (ret  == EDT_WAIT_OK || ret == EDT_WAIT_TIMEOUT)
02609         edt_p->donecount = tmpcnt;
02610 
02611     /* avoid error if close happened in another thread */
02612 
02613     if (edt_p->ring_buffer_numbufs)
02614         bufnum = (edt_p->donecount - 1) % edt_p->ring_buffer_numbufs;
02615     else
02616         return NULL;
02617 
02618 #ifdef VXWORKS
02619     /* TODO - move this to dma done */
02620     /* ATTN - not right - should be bytecount? */
02621     CACHE_DMA_INVALIDATE(edt_p->ring_buffers[bufnum],
02622         edt_p->rb_control[bufnum].size);
02623 #if defined(AV3_BOARD)
02624     printf("cache inv %x %x\n",
02625         edt_p->ring_buffers[bufnum], edt_p->rb_control[bufnum].size);
02626     bslPpcCacheInv(edt_p->ring_buffers[bufnum], edt_p->rb_control[bufnum].size);
02627 #endif
02628 #endif
02629 
02630     edt_p->last_wait_ret = ret;
02631 
02632     return (edt_p->ring_buffers[bufnum]);
02633 
02634 }
02635 
02660 int
02661 edt_get_timestamp(EdtDev * edt_p, u_int * timep, u_int bufnum)
02662 {
02663     /* we return sec and nsec - change to usec */
02664     u_int   timevals[3];
02665 
02666     timevals[0] = bufnum;
02667     if (edt_p->devid == DMY_ID)
02668     {
02669         u_int inttime ;
02670         double testtime ;
02671         timevals[0] = bufnum ;
02672         testtime = edt_timestamp();
02673         inttime = (u_int)testtime ;
02674         testtime -= inttime ;
02675         *timep++ = inttime ;
02676         *timep++ = (u_int)(testtime * 1000000.0) ;
02677     }
02678     else
02679     {
02680         edt_ioctl(edt_p, EDTG_TMSTAMP, timevals);
02681 
02682         edt_msg(EDTDEBUG, "%x %x %x %x ", bufnum,
02683             timevals[0],
02684             timevals[1],
02685             timevals[2]);
02686         *timep++ = timevals[1];
02687         *timep++ = timevals[2];
02688     }
02689 
02690     return (timevals[0]);
02691 }
02692 
02705 unsigned char *
02706 edt_wait_for_next_buffer(EdtDev *edt_p)
02707 
02708 {
02709     bufcnt_t count;
02710     unsigned int bufnum;
02711 #ifdef _NT_
02712     int timeoutval = edt_get_rtimeout(edt_p);
02713 #endif
02714 
02715     edt_ioctl(edt_p, EDTG_BUFDONE, &count);
02716     count++;
02717     if (edt_p->ring_buffer_numbufs == 0) {
02718         /* maybe they forgot edt_configure_ring_buffers */
02719         return NULL;
02720     }
02721     bufnum = (count - 1) % edt_p->ring_buffer_numbufs;
02722 
02723 #ifdef _NT_
02724     if (edt_get_drivertype(edt_p) != EDT_WDM_DRIVER)
02725 
02726     {
02727         HANDLE event;
02728         int rc;
02729 
02730         if (!edt_p->event_funcs[EDT_EVENT_BUF].wait_event)
02731         {
02732             edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
02733         }
02734 
02735         event = edt_p->event_funcs[EDT_EVENT_BUF].wait_event;
02736 
02737         while (edt_done_count(edt_p) < (bufcnt_t) count)
02738         {
02739 
02740             /* wait for event */
02741 
02742             if (timeoutval == 0)
02743                 timeoutval = INFINITE;
02744 
02745             rc = WaitForSingleObject(event, timeoutval);
02746 
02747             if (rc == WAIT_TIMEOUT)
02748             {
02749                 edt_msg(EDTDEBUG, "timeout...\n");
02750 
02751                 /* deal with timeout */
02752 
02753                 edt_do_timeout(edt_p);
02754                 ResetEvent(event) ;
02755 
02756                 break;
02757             }
02758 
02759         }
02760 
02761     }
02762     else
02763     {
02764         edt_ioctl(edt_p, EDTS_WAITBUF, &count);
02765     }
02766 #else
02767 
02768     edt_ioctl(edt_p, EDTS_WAITBUF, &count);
02769 
02770 #endif
02771 
02772     edt_msg(EDTDEBUG, "edt_wait_for_next_buffer %d done\n", count);
02773     edt_p->donecount = count;
02774     return (edt_p->ring_buffers[bufnum]);
02775 }
02776 
02777 
02792 unsigned char *
02793 edt_get_current_dma_buf(EdtDev * edt_p)
02794 {
02795     unsigned int count;
02796     unsigned int bufnum;
02797     unsigned int todo ;
02798     /* find out how many are done */
02799 
02800     edt_ioctl(edt_p, EDTG_BUFDONE, &count);
02801 
02802     todo = edt_get_todo(edt_p);
02803 
02804     /* if a dma is currently started
02805     * go to next buffer */
02806 
02807     if (todo == 0 || todo > count)
02808         count ++;
02809 
02810     bufnum = (count - 1) % edt_p->ring_buffer_numbufs;
02811 
02812     return (edt_p->ring_buffers[bufnum]);
02813 
02814 }
02815 
02836 unsigned char *
02837 edt_check_for_buffers(EdtDev *edt_p, uint_t count)
02838 {
02839     unsigned int driver_count;
02840     unsigned int bufnum;
02841     unsigned int target;
02842 
02843     target = count + edt_p->donecount;
02844     bufnum = (target - 1) % edt_p->ring_buffer_numbufs;
02845     edt_ioctl(edt_p, EDTG_BUFDONE, &driver_count);
02846     if (driver_count >= target)
02847     {
02848         return edt_wait_for_buffers(edt_p, count);
02849     }
02850     else
02851         return (NULL);
02852 }
02853 
02869 bufcnt_t
02870 edt_done_count(EdtDev * edt_p)
02871 {
02872     bufcnt_t  donecount = 0;
02873 
02874     if (edt_p->devid == DMY_ID)
02875     {
02876         if (edt_p->dd_p)
02877         {
02878             donecount = dmy_started;
02879         }
02880         else printf("DEBUG - dd_p not set for DMY_ID\n") ;
02881     }
02882     else
02883         edt_ioctl(edt_p, EDTG_BUFDONE, &donecount);
02884     return (donecount);
02885 }
02886 
02887 uint_t
02888 edt_overflow(EdtDev * edt_p)
02889 {
02890     uint_t  overflow;
02891 
02892     edt_ioctl(edt_p, EDTG_OVERFLOW, &overflow);
02893     return (overflow);
02894 }
02895 
02896 
02908 void
02909 edt_perror(char *errstr)
02910 {
02911 #ifdef _NT_
02912     LPVOID  lpMsgBuf;
02913 
02914     FormatMessage(
02915         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
02916         NULL,
02917         GetLastError(),
02918         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),      /* Default language */
02919         (LPTSTR) & lpMsgBuf,
02920         0,
02921         NULL
02922         );
02923 
02924     edt_msg(EDTWARN, "%s: %s\n", errstr, lpMsgBuf);
02925 #else
02926     edt_msg_perror(EDTWARN, errstr);
02927 #endif
02928 }
02929 
02946 u_int
02947 edt_errno(void)
02948 {
02949 #ifdef _NT_
02950     return GetLastError();
02951 #else
02952     extern int errno;
02953     return errno;
02954 #endif
02955 }
02956 
02973 uint_t
02974 edt_reg_read(EdtDev * edt_p, uint_t desc)
02975 {
02976     int     ret;
02977     edt_buf buf = {0, 0};
02978 
02979 
02980 #ifdef USB
02981     if (EDT_REG_TYPE(desc) == REMOTE_USB_TYPE)
02982     {
02983         buf.value = usb_reg_read(edt_p, desc) ;
02984     }
02985     else
02986 #endif /* USB */
02987     {
02988         buf.desc = desc;
02989         ret = edt_ioctl(edt_p, EDTG_REG, &buf);
02990         if (ret < 0)
02991             return ret;
02992     }
02993 
02994     if (dump_reg_access)
02995     {
02996         if (is_reg_dumpable(desc))
02997         {
02998             printf("%d: reg read  %08x %08x\n", edt_p->channel_no, desc, (uint_t) buf.value);
02999         }
03000     }
03001 
03002     return (u_int) buf.value;
03003 }
03004 
03020 uint_t
03021 edt_reg_or(EdtDev * edt_p, uint_t desc, uint_t mask)
03022 {
03023     int     ret;
03024     uint_t  val;
03025     edt_buf buf;
03026 
03027     buf.desc = desc;
03028     buf.value = mask;
03029     ret = edt_ioctl(edt_p, EDTS_REG_OR, &buf);
03030     if (ret < 0)
03031         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_OR)");
03032 
03033     if (dump_reg_access)
03034     {
03035         if (is_reg_dumpable(desc))
03036         {
03037             printf("%d: reg or    %08x %08x\n", edt_p->channel_no,
03038                         desc, (uint_t) buf.value);
03039         }
03040     }
03041     val = (u_int) buf.value;
03042     return val;
03043 
03044 }
03045 
03061 uint_t
03062 edt_reg_and(EdtDev * edt_p, uint_t desc, uint_t mask)
03063 {
03064     int     ret;
03065     uint_t  val;
03066     edt_buf buf;
03067 
03068     buf.desc = desc;
03069     buf.value = mask;
03070     ret = edt_ioctl(edt_p, EDTS_REG_AND, &buf);
03071     if (ret < 0)
03072         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_AND)");
03073 
03074     if (dump_reg_access)
03075     {
03076         if (is_reg_dumpable(desc))
03077         {
03078             printf("%d: reg and   %08x %08x\n", edt_p->channel_no, desc, (uint_t) buf.value);
03079         }
03080     }
03081 
03082     val = (u_int) buf.value;
03083     return val;
03084 }
03085 
03098 void
03099 edt_reg_clearset(EdtDev * edt_p, uint_t desc, uint_t mask)
03100 {
03101     int     ret;
03102     edt_buf buf;
03103 
03104     buf.desc = desc;
03105     buf.value = mask;
03106     ret = edt_ioctl(edt_p, EDTS_REG_BIT_CLEARSET, &buf);
03107     if (ret < 0)
03108         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_BIT_CLEARSET)");
03109 
03110     return;
03111 }
03112 
03124 void
03125 edt_reg_setclear(EdtDev * edt_p, uint_t desc, uint_t mask)
03126 {
03127     int     ret;
03128     edt_buf buf;
03129 
03130     buf.desc = desc;
03131     buf.value = mask;
03132     ret = edt_ioctl(edt_p, EDTS_REG_BIT_SETCLEAR, &buf);
03133     if (ret < 0)
03134         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_BIT_SETCLEAR)");
03135 
03136     return;
03137 }
03138 
03155 void
03156 edt_reg_write(EdtDev * edt_p, uint_t desc, uint_t value)
03157 {
03158     int     ret;
03159     edt_buf buf;
03160 
03161 #ifdef USB
03162     if (edt_p->devtype == USB_ID)
03163     {
03164         usb_reg_write(edt_p, desc, value) ;
03165     }
03166     else
03167 #endif /* USB */
03168     {
03169         buf.desc = desc;
03170         buf.value = value;
03171 
03172         ret = edt_ioctl(edt_p, EDTS_REG, &buf);
03173         if (ret < 0)
03174             edt_msg_perror(EDTFATAL, "write");
03175 
03176         if (dump_reg_access)
03177         {
03178             if (is_reg_dumpable(desc))
03179             {
03180                 printf("%d: reg write %08x %08x\n", edt_p->channel_no,
03181                         desc, (uint_t) buf.value);
03182             }
03183         }
03184     }
03185 }
03186 
03209 void
03210 edt_startdma_action(EdtDev * edt_p, uint_t val)
03211 {
03212     (void) edt_ioctl(edt_p, EDTS_STARTACT, &val);
03213 }
03214 
03245 void
03246 edt_enddma_action(EdtDev * edt_p, uint_t val)
03247 {
03248     (void) edt_ioctl(edt_p, EDTS_ENDACT, &val);
03249 }
03250 
03270 void
03271 edt_startdma_reg(EdtDev * edt_p, uint_t desc, uint_t val)
03272 {
03273     int     ret;
03274     edt_buf buf;
03275 
03276     buf.desc = desc;
03277     buf.value = val;
03278     ret = edt_ioctl(edt_p, EDTS_STARTDMA, &buf);
03279     if (ret < 0)
03280         edt_msg_perror(EDTFATAL, "write");
03281 }
03282 
03295 void
03296 edt_enddma_reg(EdtDev * edt_p, uint_t desc, uint_t val)
03297 {
03298     int     ret;
03299     edt_buf buf;
03300 
03301     buf.desc = desc;
03302     buf.value = val;
03303     ret = edt_ioctl(edt_p, EDTS_ENDDMA, &buf);
03304     if (ret < 0)
03305         edt_msg_perror(EDTFATAL, "write");
03306 }
03307 
03308 
03309 
03341 void
03342 edt_read_start_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03343                       u_char set, u_char clear, u_char setclear, u_char clearset,
03344                       int delay1, int delay2)
03345 {
03346     edt_buf buf;
03347     u_int delays;
03348 
03349     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03350     (void) edt_ioctl(edt_p, EDTS_READ_START_DELAYS, &delays);
03351 
03352     buf.flags = enable;
03353     buf.desc  = reg_desc;
03354     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03355 
03356     (void) edt_ioctl(edt_p, EDTS_READ_STARTACT, &buf);
03357 }
03358 
03359 
03360 
03392 void
03393 edt_read_end_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03394                     u_char set, u_char clear, u_char setclear, u_char clearset,
03395                     int delay1, int delay2)
03396 {
03397     edt_buf buf;
03398     u_int delays;
03399 
03400     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03401     (void) edt_ioctl(edt_p, EDTS_READ_END_DELAYS, &delays);
03402 
03403     buf.flags = enable;
03404     buf.desc  = reg_desc;
03405     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03406 
03407     (void) edt_ioctl(edt_p, EDTS_READ_ENDACT, &buf);
03408 }
03409 
03410 
03411 
03443 void
03444 edt_write_start_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03445                        u_char set, u_char clear, u_char setclear, u_char clearset,
03446                        int delay1, int delay2)
03447 {
03448     edt_buf buf;
03449     u_int delays;
03450 
03451     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03452     (void) edt_ioctl(edt_p, EDTS_WRITE_START_DELAYS, &delays);
03453 
03454     buf.flags = enable;
03455     buf.desc  = reg_desc;
03456     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03457 
03458     (void) edt_ioctl(edt_p, EDTS_WRITE_STARTACT, &buf);
03459 }
03460 
03461 
03462 
03494 void
03495 edt_write_end_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03496                      u_char set, u_char clear, u_char setclear, u_char clearset,
03497                      int delay1, int delay2)
03498 {
03499     edt_buf buf;
03500     u_int delays;
03501 
03502     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03503     (void) edt_ioctl(edt_p, EDTS_WRITE_END_DELAYS, &delays);
03504 
03505     buf.flags = enable;
03506     buf.desc  = reg_desc;
03507     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03508 
03509     (void) edt_ioctl(edt_p, EDTS_WRITE_ENDACT, &buf);
03510 }
03511 
03512 
03513 
03534 u_char
03535 edt_intfc_read(EdtDev * edt_p, uint_t offset)
03536 {
03537     u_int   read;
03538 
03539     read = edt_reg_read(edt_p, INTFC_BYTE | (offset & 0xffff));
03540     return ((u_char) read & 0xff);
03541 }
03542 
03564 void
03565 edt_intfc_write(EdtDev * edt_p, uint_t offset, u_char data)
03566 {
03567     edt_reg_write(edt_p, INTFC_BYTE | (offset & 0xffff), data);
03568 }
03569 
03604 u_short
03605 edt_intfc_read_short(EdtDev * edt_p, uint_t offset)
03606 {
03607     u_int   read;
03608 
03609     read = edt_reg_read(edt_p, INTFC_WORD | (offset & 0xffff));
03610     return (read & 0xffff);
03611 }
03612 
03635 void
03636 edt_intfc_write_short(EdtDev * edt_p, uint_t offset, u_short data)
03637 {
03638     edt_reg_write(edt_p, INTFC_WORD | (offset & 0xffff), data);
03639 }
03640 
03655 uint_t
03656 edt_intfc_read_32(EdtDev * edt_p, uint_t offset)
03657 {
03658     uint_t  read;
03659 
03660     read = edt_reg_read(edt_p, INTFC_32 | (offset & 0xffff));
03661     return (read);
03662 }
03663 
03679 void
03680 edt_intfc_write_32(EdtDev * edt_p, uint_t offset, uint_t data)
03681 {
03682     edt_reg_write(edt_p, INTFC_32 | (offset & 0xffff), data);
03683 }
03684 
03685 
03686 int
03687 edt_set_rci_chan(EdtDev *edt_p, int unit, int channel)
03688 {
03689     int ret ;
03690     edt_buf buf;
03691     buf.desc = unit;
03692     buf.value = channel;
03693     edt_msg(EDTDEBUG, "set rci unit %d chan %d\n",unit,channel) ;
03694     ret = edt_ioctl(edt_p, EDTS_RCI_CHAN, &buf);
03695     return (ret) ;
03696 }
03697 
03698 int
03699 edt_get_rci_chan(EdtDev *edt_p, int unit)
03700 {
03701     int channel ;
03702     edt_buf buf;
03703     buf.desc = unit;
03704     edt_ioctl(edt_p, EDTG_RCI_CHAN, &buf);
03705     channel = (u_int) buf.value ;
03706     edt_msg(EDTDEBUG, "get rci unit %d chan %d\n",unit,channel) ;
03707     return (channel) ;
03708 }
03709 
03710 int
03711 edt_set_rci_dma(EdtDev * edt_p, int unit, int channel)
03712 
03713 {
03714     char msg[5];
03715     sprintf(msg,"D %d",channel);
03716 
03717     edt_send_msg(edt_p,unit,msg,3);
03718     edt_set_rci_chan(edt_p, unit, channel) ;
03719 
03720     return 0;
03721 }
03722 
03723 int
03724 edt_get_rci_dma(EdtDev * edt_p, int unit)
03725 
03726 {
03727     char msgbuf[5];
03728     int channel;
03729     msgbuf[1] = 0;
03730 
03731     edt_send_msg(edt_p, unit, "D", 1);
03732     edt_serial_wait(edt_p, 100, 0) ;
03733     edt_get_msg(edt_p, msgbuf, sizeof(msgbuf));
03734 
03735     channel = atoi(&msgbuf[2]);
03736 
03737     return channel;
03738 
03739 }
03740 
03755 int
03756 edt_set_burst_enable(EdtDev * edt_p, int onoff)
03757 {
03758     return (edt_ioctl(edt_p, EDTS_BURST_EN, &onoff));
03759 }
03760 
03761 
03775 int
03776 edt_get_burst_enable(EdtDev * edt_p)
03777 {
03778     int     val;
03779 
03780     edt_ioctl(edt_p, EDTG_BURST_EN, &val);
03781     return (val);
03782 }
03783 
03784 int
03785 edt_set_continuous(EdtDev * edt_p, int val)
03786 {
03787 #ifdef PDV
03788     u_int tmp ;
03789     tmp = edt_p->dd_p->datapath_reg ;
03790     /* tmp = edt_reg_read(edt_p, PDV_DATA_PATH) & ~PDV_CONTINUOUS ;*/
03791     edt_ioctl(edt_p, EDTS_PDVDPATH, &tmp);
03792     return (edt_ioctl(edt_p, EDTS_PDVCONT, &val));
03793 #else
03794     return 0;
03795 #endif
03796 }
03797 
03798 void
03799 edt_reset_counts(EdtDev * edt_p)
03800 {
03801     int     dmy;
03802 
03803     edt_ioctl(edt_p, EDTS_RESETCOUNT, &dmy);
03804 }
03805 
03806 void
03807 edt_reset_serial(EdtDev * edt_p)
03808 {
03809     int     dmy;
03810 
03811     dmy = edt_p->channel_no ;
03812     edt_ioctl(edt_p, EDTS_RESETSERIAL, &dmy);
03813 }
03814 
03815 
03816 void
03817 edt_flush_channel(EdtDev *edt_p, int channel)
03818 
03819 {
03820     u_int dma_cfg = edt_reg_read(edt_p, EDT_DMA_CFG) ;
03821 
03822     dma_cfg &= ~(EDT_EMPTY_CHAN | EDT_EMPTY_CHAN_FIFO) ;
03823 
03824     /*
03825     * Set the channel number and enable the rfifo and related logic.
03826     */
03827     dma_cfg |= ((channel << EDT_EMPTY_CHAN_SHIFT) | EDT_RFIFO_ENB) ;
03828     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03829 
03830     /*
03831     * Set then reset the channel fifo flush bit.
03832     */
03833     dma_cfg |= EDT_EMPTY_CHAN_FIFO ;
03834     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03835 
03836     dma_cfg &= ~EDT_EMPTY_CHAN_FIFO ;
03837     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03838 
03839 
03840 }
03841 
03842 #if defined( PCD )
03843 
03844 u_char
03845 pcd_get_option(EdtDev * edt_p)
03846 {
03847     return (edt_intfc_read(edt_p, PCD_OPTION));
03848 }
03849 
03850 u_char
03851 pcd_get_cmd(EdtDev * edt_p)
03852 {
03853     return (edt_intfc_read(edt_p, PCD_CMD));
03854 }
03855 
03856 void
03857 pcd_set_cmd(EdtDev * edt_p, u_char val)
03858 {
03859     edt_intfc_write(edt_p, PCD_CMD, val);
03860 }
03861 
03862 u_char
03863 pcd_get_funct(EdtDev * edt_p)
03864 {
03865     return (edt_intfc_read(edt_p, PCD_FUNCT));
03866 }
03867 
03868 void
03869 pcd_set_funct(EdtDev * edt_p, u_char val)
03870 {
03871     edt_intfc_write(edt_p, PCD_FUNCT, val);
03872 }
03873 
03874 u_char
03875 pcd_get_stat(EdtDev * edt_p)
03876 {
03877     return ((u_char) edt_intfc_read(edt_p, PCD_STAT));
03878 }
03879 
03880 u_char
03881 pcd_get_stat_polarity(EdtDev * edt_p)
03882 {
03883     return (edt_intfc_read(edt_p, PCD_STAT_POLARITY));
03884 }
03885 
03886 void
03887 pcd_set_stat_polarity(EdtDev * edt_p, u_char val)
03888 {
03889     u_char polarity = edt_intfc_read(edt_p, PCD_STAT_POLARITY);
03890 
03891     polarity &= 0xF0;
03892     polarity |= val;
03893     
03894     edt_intfc_write(edt_p, PCD_STAT_POLARITY, polarity);
03895 }
03896 
03897 void
03898 pcd_set_byteswap(EdtDev * edt_p, int val)
03899 {
03900     u_char  tmp;
03901 
03902     tmp = edt_intfc_read(edt_p, PCD_CONFIG);
03903     if (val)
03904         tmp |= PCD_BYTESWAP;
03905     else
03906         tmp &= ~PCD_BYTESWAP;
03907     edt_intfc_write(edt_p, PCD_CONFIG, tmp);
03908 }
03909 
03910 
03911 
03912 void
03913 pcd_flush_channel(EdtDev * edt_p, int channel)
03914 {
03915     u_short ssd16_chen = edt_reg_read(edt_p, SSD16_CHEN) ;
03916 
03917     ssd16_chen &= ~(1 << channel);
03918     edt_reg_write(edt_p, SSD16_CHEN, ssd16_chen) ;
03919 
03920     edt_flush_channel(edt_p,channel);
03921 
03922 
03923     ssd16_chen |= (1 << channel);
03924     edt_reg_write(edt_p, SSD16_CHEN, ssd16_chen) ;
03925 
03926 }
03927 
03928 /*****************************************************************************
03929 *
03930 * pio routines:  programmed I/O for PCD DMA boards.
03931 *
03932 *****************************************************************************/
03933 
03934 void
03935 pcd_pio_init(EdtDev *edt_p)
03936 {
03937     static u_char * mapaddr = 0 ;
03938 
03939     if (mapaddr == 0)
03940     {
03941         mapaddr = (u_char *) edt_mapmem(edt_p, 0, 256) ;
03942         edt_p->reg_fifo_io  = (u_int *)(mapaddr + (EDT_GP_OUTPUT & 0xff)) ;
03943         edt_p->reg_fifo_cnt  = (u_char *)(mapaddr + (EDT_DMA_CFG & 0xff) + 3) ;
03944         edt_p->reg_fifo_ctl = (u_char *)(mapaddr + (EDT_DMA_CFG & 0xff) + 1) ;
03945         edt_p->reg_intfc_off  = (volatile u_char *) mapaddr + (EDT_REMOTE_OFFSET & 0xff) ;
03946         edt_p->reg_intfc_dat = (volatile u_char *) mapaddr + (EDT_REMOTE_DATA & 0xff) ;
03947     }
03948     pcd_pio_intfc_write(edt_p, PCD_DIRB, 0xcc);
03949     pcd_pio_flush_fifo(edt_p) ;
03950 }
03951 
03952 void
03953 pcd_pio_intfc_write(EdtDev *edt_p, u_int desc, u_char val)
03954 {
03955     int dmy ;
03956 
03957     if (edt_p->reg_intfc_off == NULL)
03958         return;
03959 
03960     *edt_p->reg_intfc_off = desc & 0xff ;
03961     dmy = *edt_p->reg_intfc_off ;
03962 
03963     *edt_p->reg_intfc_dat = val ;
03964     dmy = *edt_p->reg_intfc_dat ;
03965 }
03966 
03967 u_char
03968 pcd_pio_intfc_read(EdtDev *edt_p, u_int desc)
03969 {
03970     int dmy ;
03971 
03972     if (edt_p->reg_intfc_off == NULL)
03973         return 0;
03974 
03975     *edt_p->reg_intfc_off = desc & 0xff ;
03976     dmy = *edt_p->reg_intfc_off ;
03977 
03978     return(*edt_p->reg_intfc_dat) ;
03979 }
03980 
03981 
03982 
03983 void
03984 pcd_pio_set_direction(EdtDev *edt_p, int direction)
03985 {
03986     u_char  cmd = pcd_pio_intfc_read(edt_p, PCD_CMD) ;
03987 
03988     if (direction)
03989     {
03990         pcd_pio_intfc_write(edt_p, PCD_DIRA, 0x0f);
03991 
03992         cmd &= ~PCD_DIR;
03993         cmd |= PCD_ENABLE;
03994 
03995     }
03996     else
03997     {
03998         pcd_pio_intfc_write(edt_p, PCD_DIRA, 0xf0);
03999 
04000         cmd |= PCD_DIR | PCD_ENABLE ;
04001     }
04002 
04003     pcd_pio_intfc_write(edt_p, PCD_CMD, cmd);
04004 }
04005 
04006 static void
04007 pcd_pio_quick_flush(EdtDev *edt_p)
04008 {
04009     u_char tmpc ;
04010 
04011     if (edt_p->reg_fifo_ctl == NULL)
04012         return;
04013 
04014     tmpc = *edt_p->reg_fifo_ctl ;
04015     tmpc &= ~1 ;
04016     *edt_p->reg_fifo_ctl = tmpc ;
04017     tmpc |= 1 ;
04018     *edt_p->reg_fifo_ctl = tmpc ;
04019 }
04020 
04021 
04022 void
04023 pcd_pio_flush_fifo(EdtDev * edt_p)
04024 {
04025     unsigned char cmd;
04026     unsigned int dmy;
04027 
04028     if (edt_p->reg_intfc_off == NULL)
04029         return;
04030 
04031     /* reset the interface fifos */
04032     *edt_p->reg_intfc_off = PCD_CMD & 0xff ;
04033     dmy = *edt_p->reg_intfc_off ;
04034     cmd = *edt_p->reg_intfc_dat ;
04035     cmd &= ~PCD_ENABLE;
04036     *edt_p->reg_intfc_dat = cmd ;
04037     dmy = *edt_p->reg_intfc_dat ;
04038     cmd |= PCD_ENABLE;
04039     *edt_p->reg_intfc_dat = cmd ;
04040     dmy = *edt_p->reg_intfc_dat ;
04041 
04042     pcd_pio_quick_flush(edt_p) ;
04043 
04044 }
04045 
04046 int
04047 pcd_pio_write(EdtDev *edt_p, u_char *buf, int size)
04048 {
04049     int i;
04050     u_int *tmpl = (u_int *) buf ;
04051 
04052     if (edt_p->reg_fifo_io == NULL)
04053         return -1;
04054 
04055     pcd_pio_set_direction(edt_p, EDT_WRITE) ;
04056 
04057     for (i = 0 ; i < size / 4 ; i++)
04058         *edt_p->reg_fifo_io = *tmpl++ ;
04059 
04060     return(size);
04061 }
04062 
04063 int
04064 pcd_pio_read(EdtDev *edt_p, u_char *buf, int size)
04065 {
04066     u_int *tmpl = (u_int *) buf ;
04067     int wordcnt = 0 ;
04068     int words_avail ;
04069     int words_requested = size / 4 ;
04070 
04071     if (edt_p->reg_fifo_io == NULL)
04072         return -1;
04073 
04074     pcd_pio_set_direction(edt_p, EDT_READ) ;
04075 
04076     while (wordcnt < words_requested)
04077     {
04078         words_avail = *edt_p->reg_fifo_cnt & 0xf ;
04079 
04080         while (words_avail && wordcnt < words_requested)
04081         {
04082             -- words_avail ;
04083             *tmpl = *edt_p->reg_fifo_io ;
04084             wordcnt++ ;
04085             tmpl++ ;
04086         }
04087 
04088         if ((wordcnt == words_requested - 1) && (*edt_p->reg_fifo_cnt & 0x1f) == 0x10)
04089         {
04090             *tmpl = *edt_p->reg_fifo_io ;
04091             wordcnt++ ;
04092         }
04093     }
04094 
04095     pcd_pio_quick_flush(edt_p);
04096 
04097     return(size) ;
04098 }
04099 
04100 void
04101 pcd_set_abortdma_onintr(EdtDev *edt_p, int flag)
04102 {
04103     if (flag == 0)
04104     {
04105         edt_reg_and(edt_p, PCD_CMD, ~PCD_STAT_INT_1) ;
04106     }
04107 
04108     edt_ioctl(edt_p, EDTS_ABORTDMA_ONINTR, &flag) ;
04109 
04110     if (flag)
04111     {
04112         edt_reg_or(edt_p, PCD_CMD, PCD_STAT_INT_1 | PCD_ENABLE) ;
04113         edt_reg_or(edt_p, PCD_STAT_POLARITY, PCD_STAT_INT_ENA) ;
04114         edt_set_remote_intr(edt_p, TRUE);
04115     }
04116 }
04117 
04118 #endif                          /* PCD */
04119 
04120 
04121 
04130 void
04131 edt_flush_fifo(EdtDev * edt_p)
04132 {
04133     uint_t  tmp;
04134     unsigned char cmd;
04135     unsigned char cfg;
04136     unsigned int dmy;
04137 
04138     edt_msg(EDTDEBUG, "edt_flush_fifo\n") ;
04139     /* Turn off the PCI fifo */
04140     tmp = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04141     tmp &= (~EDT_RFIFO_ENB);
04142     edt_reg_write(edt_p, EDT_DMA_INTCFG, tmp);
04143     dmy = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04144 
04145     if (edt_is_pcd(edt_p) || edt_p->devid == PDVAERO_ID)
04146     {
04147         /* reset the interface fifos */
04148         cmd = edt_intfc_read(edt_p, PCD_CMD);
04149         cmd &= ~PCD_ENABLE;
04150         edt_intfc_write(edt_p, PCD_CMD, cmd);
04151         dmy = edt_intfc_read(edt_p, PCD_CMD);
04152         cmd |= PCD_ENABLE;
04153         edt_intfc_write(edt_p, PCD_CMD, cmd);
04154         dmy = edt_intfc_read(edt_p, PCD_CMD);
04155     }
04156     else if (edt_is_pdv(edt_p))
04157     {
04158         int cont = edt_reg_read(edt_p, PDV_DATA_PATH) & PDV_CONTINUOUS;
04159 
04160         cfg = edt_intfc_read(edt_p, PDV_CFG);
04161         cfg &= ~PDV_FIFO_RESET;
04162         edt_intfc_write(edt_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
04163         edt_intfc_write(edt_p, PDV_CMD, PDV_RESET_INTFC);
04164         edt_intfc_write(edt_p, PDV_CFG, cfg);
04165 
04166         if (cont)
04167             edt_reg_or(edt_p,PDV_DATA_PATH, PDV_CONTINUOUS);
04168     }
04169 
04170 
04171     /* Turn     on the PCI fifos, which flushes them */
04172     tmp |= (EDT_RFIFO_ENB);
04173     edt_reg_write(edt_p, EDT_DMA_INTCFG, tmp);
04174     dmy = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04175 
04176 }
04177 
04195 uint_t
04196 edt_get_bytecount(EdtDev * edt_p)
04197 {
04198     uint_t  tmp;
04199 
04200     if (edt_ioctl(edt_p, EDTG_BYTECOUNT, &tmp) < 0)
04201         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_BYTECOUNT)");
04202 
04203     return (tmp);
04204 }
04205 
04215 uint_t
04216 edt_get_timeout_count(EdtDev * edt_p)
04217 {
04218     uint_t  tmp;
04219 
04220     if (edt_ioctl(edt_p, EDTG_TIMECOUNT, &tmp) < 0)
04221         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_TIMECOUNT)");
04222 
04223     return (tmp);
04224 }
04229 unsigned short
04230 edt_get_direction(EdtDev * edt_p)
04231 {
04232     unsigned short dirreg;
04233 
04234     /* Set the direction register for DMA output */
04235     dirreg = edt_intfc_read(edt_p, PCD_DIRA);
04236     dirreg |= edt_intfc_read(edt_p, PCD_DIRB) << 8;
04237     return (dirreg);
04238 }
04239 
04250 int
04251 edt_cancel_current_dma(EdtDev * edt_p)
04252 {
04253     unsigned int finish_current = 0;
04254 
04255     return edt_ioctl(edt_p, EDTS_STOPBUF, &finish_current);
04256 }
04257 
04258 
04270 void
04271 edt_set_direction(EdtDev * edt_p, int direction)
04272 {
04273 
04274     u_int tmp = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04275 
04276     if (edt_is_pcd(edt_p) || edt_p->devid == PDVAERO_ID)
04277     {
04278         edt_ioctl(edt_p, EDTS_DIRECTION, &direction);
04279     }
04280 
04281     tmp |= (EDT_RFIFO_ENB);
04282     edt_reg_write(edt_p, EDT_DMA_INTCFG, tmp);
04283 
04284     edt_p->last_direction = (direction) ? 2: 1;
04285 
04286 }
04287 
04288 /*
04289 * EDT IOCTL Interface Routines
04290 *
04291 * DESCRIPTION General   Purpose device control layer for EDT PCI and SBus
04292 * interface products
04293 *
04294 * All routines access a specific device, whose handle is created and returned
04295 * by    the <device>_open() routine.
04296 */
04297 
04298 
04299 #ifndef TRUE
04300 #define TRUE 1
04301 #endif
04302 #ifndef FALSE
04303 #define FALSE 0
04304 #endif
04305 
04306 
04316 int
04317 edt_ioctl(EdtDev * edt_p, int code, void *arg)
04318 {
04319     int     get, set;
04320     int     size;
04321     edt_ioctl_struct eis;
04322 #ifdef __APPLE__
04323     int     ret ;
04324 #endif
04325 
04326 #if 0 /* produces too much output for the normal case, but may still be useful...*/
04327     edt_msg(EDTDEBUG, "edt_ioctl(%04x, %04x)\n", code, arg);
04328 #endif
04329 
04330     if (edt_p->devid == DMY_ID)
04331         return (0);
04332     memset(&eis,0, sizeof(eis));
04333     eis.device = edt_p->fd;
04334     eis.controlCode = EIO_DECODE_ACTION(code);
04335     size = EIO_DECODE_SIZE(code);
04336     set = EIO_DECODE_SET(code);
04337     get = EIO_DECODE_GET(code);
04338     eis.inSize = 0;
04339     eis.inBuffer = NULL;
04340     eis.outSize = 0;
04341     eis.outBuffer = NULL;
04342     eis.bytesReturned = 0 ;
04343 #ifdef __APPLE__
04344     eis.channel = edt_p->channel_no ;
04345     eis.unit = edt_p->unit_no ;
04346 #endif
04347 
04348 
04349     if (set)
04350     {
04351         eis.inSize = size;
04352         eis.inBuffer = arg;
04353     }
04354 
04355     if (get)
04356     {
04357         eis.outSize = size;
04358         eis.outBuffer = arg;
04359     }
04360 
04361 
04362 #ifdef _NT_
04363 
04364     if (!DeviceIoControl(
04365         (HANDLE) edt_p->fd,
04366         EDT_MAKE_IOCTL(EDT_DEVICE_TYPE, eis.controlCode),
04367         eis.inBuffer,
04368         eis.inSize,
04369         eis.outBuffer,
04370         eis.outSize,
04371         (LPDWORD)&eis.bytesReturned,
04372         NULL))
04373     {
04374         return -1;
04375     }
04376     return 0;
04377 
04378 #else
04379 #ifdef VXWORKS
04380     return ioctl(edt_p->fd, EDT_NT_IOCTL, (int)&eis);
04381 #else
04382 #if defined(__APPLE__)
04383 
04384     eis.device = edt_p->channel_no ;
04385     ret = edt_mac_ioctl((u_int)edt_p->fd, EDT_NT_IOCTL, &eis) ;
04386     return(ret);
04387 #else
04388     return ioctl(edt_p->fd, EDT_NT_IOCTL, &eis);
04389 #endif /* apple */
04390 #endif
04391 #endif
04392 
04393 }
04394 
04395 int
04396 edt_ioctl_nt(EdtDev * edt_p, int controlCode, void *inBuffer, int inSize,
04397              void *outBuffer, int outSize, int *bytesReturned)
04398 {
04399     int     ret = 0;
04400 
04401     edt_ioctl_struct eis;
04402 
04403     eis.device = edt_p->fd;
04404     eis.controlCode = controlCode;
04405     eis.inBuffer = inBuffer;
04406     eis.inSize = inSize;
04407     eis.outBuffer = outBuffer;
04408     eis.outSize = outSize;
04409     eis.bytesReturned = 0;
04410 #ifdef __APPLE__
04411     eis.channel = edt_p->channel_no ;
04412     eis.unit = edt_p->unit_no ;
04413 #endif
04414 
04415 #ifdef _NT_
04416 
04417     if (inSize == 0 && outSize == 0)
04418         return ret ;
04419 
04420     if (!DeviceIoControl(
04421         eis.device,
04422         eis.controlCode,
04423         eis.inBuffer,
04424         eis.inSize,
04425         eis.outBuffer,
04426         eis.outSize,
04427         (LPDWORD) &eis.bytesReturned,
04428         NULL))
04429     {
04430 
04431     }
04432 
04433 #else
04434 #ifdef VXWORKS
04435     if ((ret = ioctl(eis.device, EDT_NT_IOCTL, (int)&eis)) == 0)
04436 #else /* vxworks */
04437 #if defined(__APPLE__)
04438     if ((ret = edt_mac_ioctl((u_int)edt_p->fd, EDT_NT_IOCTL, &eis)) == 0)
04439 #else
04440     if ((ret = ioctl(eis.device, EDT_NT_IOCTL, &eis)) == 0)
04441 #endif /* apple */
04442 #endif /* vxworks */
04443 #endif /* nt */
04444     {
04445         *bytesReturned = eis.bytesReturned;
04446     }
04447     return ret;
04448 }
04449 
04450 
04451 uint_t
04452 edt_debugval(EdtDev * edt_p)
04453 {
04454     uint_t  debugval = 0;
04455 
04456     return (debugval);
04457 }
04458 
04470 int
04471 edt_timeouts(EdtDev * edt_p)
04472 {
04473     int     timeouts;
04474 
04475     if (edt_p->devid == DMY_ID)
04476         return (0);
04477     edt_ioctl(edt_p, EDTG_TIMEOUTS, &timeouts);
04478     return (timeouts);
04479 }
04480 
04481 int
04482 edt_set_dependent(EdtDev * edt_p, void *addr)
04483 {
04484     if (addr == NULL)
04485         return (-1);
04486     if (edt_p->devid == DMY_ID)
04487     {
04488 #ifdef _NT_
04489         edt_p->fd = CreateFile(
04490             edt_p->edt_devname,
04491             GENERIC_READ | GENERIC_WRITE,
04492             FILE_SHARE_READ | FILE_SHARE_WRITE,
04493             NULL,
04494             OPEN_ALWAYS,
04495             FILE_ATTRIBUTE_NORMAL,
04496             NULL);
04497 #else
04498         if (edt_p->fd)
04499         {
04500             /* printf("fd already open\n") ;*/
04501         }
04502         else
04503         {
04504             edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666);
04505         }
04506 #endif
04507         edt_write(edt_p, addr, sizeof(Dependent));
04508 #ifdef _NT_
04509         CloseHandle(edt_p->fd);
04510         edt_p->fd = NULL;
04511 #else
04512         close(edt_p->fd);
04513         edt_p->fd = 0;
04514 #endif
04515         return (0);
04516     }
04517     return (edt_ioctl(edt_p, EDTS_DEPENDENT, addr));
04518 }
04519 
04520 int
04521 edt_get_dependent(EdtDev * edt_p, void *addr)
04522 {
04523     if (addr == NULL)
04524         return (-1);
04525     if (edt_p->devid == DMY_ID)
04526     {
04527         int ret ;
04528 #ifdef _NT_
04529         edt_p->fd = CreateFile(
04530             edt_p->edt_devname,
04531             GENERIC_READ | GENERIC_WRITE,
04532             FILE_SHARE_READ | FILE_SHARE_WRITE,
04533             NULL,
04534             OPEN_ALWAYS,
04535             FILE_ATTRIBUTE_NORMAL,
04536             NULL);
04537 #else
04538         edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666);
04539 #endif
04540         ret = edt_read(edt_p, addr, sizeof(Dependent));
04541 #ifdef _NT_
04542         CloseHandle(edt_p->fd);
04543         edt_p->fd = NULL;
04544 #else
04545         close(edt_p->fd);
04546         edt_p->fd = 0;
04547 #endif
04548         if (ret != sizeof(Dependent))
04549             return (-1) ;
04550         return (0);
04551     }
04552     return (edt_ioctl(edt_p, EDTG_DEPENDENT, addr));
04553 }
04554 
04555 int
04556 edt_dump_sglist( EdtDev * edt_p, int val)
04557 {
04558     return (edt_ioctl(edt_p, EDTS_DUMP_SGLIST, &val));
04559 }
04560 
04561 int
04562 edt_set_debug(EdtDev * edt_p, int val)
04563 {
04564     return (edt_ioctl(edt_p, EDTS_DEBUG, &val));
04565 }
04566 
04567 int
04568 edt_get_debug(EdtDev * edt_p)
04569 {
04570     int     val;
04571 
04572     edt_ioctl(edt_p, EDTG_DEBUG, &val);
04573     return (val);
04574 }
04575 
04589 int
04590 edt_set_rtimeout(EdtDev * edt_p, int value)
04591 {
04592     edt_msg(EDTDEBUG, "edt_set_rtimeout(%d)\n", value);
04593     return edt_ioctl(edt_p, EDTS_RTIMEOUT, &value);
04594 }
04595 
04611 int
04612 edt_set_wtimeout(EdtDev * edt_p, int value)
04613 {
04614     edt_msg(EDTDEBUG, "edt_set_wtimeout(%d)\n", value);
04615     return edt_ioctl(edt_p, EDTS_WTIMEOUT, &value);
04616 }
04617 
04629 int
04630 edt_get_rtimeout(EdtDev * edt_p)
04631 {
04632     int     value;
04633 
04634     edt_ioctl(edt_p, EDTG_RTIMEOUT, &value);
04635     return (value);
04636 }
04637 
04649 int
04650 edt_get_wtimeout(EdtDev * edt_p)
04651 {
04652     int     value;
04653 
04654     edt_ioctl(edt_p, EDTG_WTIMEOUT, &value);
04655     return (value);
04656 }
04657 
04658 int
04659 edt_get_tracebuf(EdtDev * edt_p, u_int * addr)
04660 {
04661     if (addr == NULL)
04662         return (-1);
04663     return (edt_ioctl(edt_p, EDTG_TRACEBUF, addr));
04664 }
04665 
04669 int
04670 edt_send_msg(EdtDev * edt_p, int unit, const char *msg, int size)
04671 {
04672     int dummy ;
04673     ser_buf ser ;
04674     ser.unit = unit ;
04675     ser.size = size ;
04676     ser.flags = EDT_SERIAL_SAVERESP ;
04677 
04678     if (size > sizeof(ser.buf))
04679     {
04680         edt_msg(EDTFATAL, "Error writing %d bytes to serial buffer\n", size);
04681         size = sizeof(ser.buf);
04682     }
04683     memcpy(ser.buf,msg,size) ;
04684 
04685     edt_ioctl_nt(edt_p, ES_SERIAL, &ser, size + EDT_SERBUF_OVRHD,
04686         NULL, 0, &dummy);
04687     return (0);
04688 }
04689 
04690 int
04691 edt_get_msg_unit(EdtDev * edt_p, char *msgbuf, int maxsize, int unit)
04692 {
04693     ser_buf ser ;
04694     int     bytes = 0;
04695     ser.unit = unit ;
04696     ser.size = maxsize ;
04697 
04698     edt_ioctl_nt(edt_p, EG_SERIAL, &ser, EDT_SERBUF_OVRHD,
04699         msgbuf, maxsize, &bytes);
04700     if (bytes < maxsize)
04701         msgbuf[bytes] = '\0';
04702     return (bytes);
04703 }
04704 
04718 int
04719 edt_get_msg(EdtDev * edt_p, char *msgbuf, int maxsize)
04720 {
04721     if (edt_is_dvcl(edt_p) || edt_is_dvfox(edt_p) || edt_p->devid == PDVAERO_ID)
04722         return(edt_get_msg_unit(edt_p, msgbuf, maxsize, edt_p->channel_no)) ;
04723     else return(edt_get_msg_unit(edt_p, msgbuf, maxsize, 0)) ;
04724 }
04725 
04726 
04727 int
04728 edt_set_statsig(EdtDev * edt_p, int event, int sig)
04729 {
04730     edt_buf buf;
04731 
04732     buf.desc = event;
04733     buf.value = sig;
04734     return (edt_ioctl(edt_p, EDTS_EVENT_SIG, &buf));
04735 }
04736 
04737 int
04738 edt_set_eodma_int(EdtDev * edt_p, int sig)
04739 {
04740     return (edt_ioctl(edt_p, EDTS_EODMA_SIG, &sig));
04741 }
04742 
04743 int
04744 edt_set_autodir(EdtDev * edt_p, int val)
04745 {
04746     return (edt_ioctl(edt_p, EDTS_AUTODIR, &val));
04747 }
04748 
04768 int
04769 edt_set_firstflush(EdtDev * edt_p, int flag)
04770 {
04771     return (edt_ioctl(edt_p, EDTS_FIRSTFLUSH, &flag));
04772 }
04773 
04774 
04798 int
04799 edt_get_firstflush(EdtDev * edt_p)
04800 {
04801 
04802     int val;
04803 
04804     edt_ioctl(edt_p, EDTG_FIRSTFLUSH, &val);
04805 
04806     return val;
04807 }
04808 
04809 
04810 u_char
04811 edt_set_funct_bit(EdtDev * edt_p, u_char mask)
04812 {
04813     unsigned char funct;
04814 
04815     funct = edt_reg_read(edt_p, PCD_FUNCT);
04816     funct |= mask;
04817     edt_reg_write(edt_p, PCD_FUNCT, funct);
04818     return (funct);
04819 }
04820 
04821 u_char
04822 edt_clr_funct_bit(EdtDev * edt_p, u_char mask)
04823 {
04824     u_char  funct;
04825 
04826     funct = edt_reg_read(edt_p, PCD_FUNCT);
04827     funct &= ~mask;
04828     edt_reg_write(edt_p, PCD_FUNCT, funct);
04829     return (funct);
04830 }
04831 
04832 
04837 static void
04838 shft_av9110(EdtDev * edt_p, u_int data, u_int numbits)
04839 {
04840     int use_pcd_method;
04841 
04842     if (ID_IS_PCD(edt_p->devid) || edt_p->devid == PDVAERO_ID)
04843         use_pcd_method = 1;
04844     else
04845         use_pcd_method = 0;
04846 
04847     while (numbits)
04848     {
04849         if (use_pcd_method)
04850         {
04851             if (data & 0x1)
04852                 edt_set_funct_bit(edt_p, EDT_FUNCT_DATA);
04853             else
04854                 edt_clr_funct_bit(edt_p, EDT_FUNCT_DATA);
04855             /* clock it in */
04856             edt_set_funct_bit(edt_p, EDT_FUNCT_CLK);
04857             edt_clr_funct_bit(edt_p, EDT_FUNCT_CLK);
04858         }
04859         else
04860         {
04861             if (data & 0x1)
04862                 edt_set_pllct_bit(edt_p, EDT_FUNCT_DATA);
04863             else
04864                 edt_clr_pllct_bit(edt_p, EDT_FUNCT_DATA);
04865             /* clock it in */
04866             edt_set_pllct_bit(edt_p, EDT_FUNCT_CLK);
04867             edt_clr_pllct_bit(edt_p, EDT_FUNCT_CLK);
04868 
04869         }
04870         data = data >> 1;
04871         numbits--;
04872     }
04873 }
04874 
04875 u_char
04876 edt_set_pllct_bit(EdtDev * edt_p, u_char mask)
04877 {
04878     unsigned char pll_ct;
04879 
04880     pll_ct = edt_reg_read(edt_p, PDV_PLL_CTL);
04881     pll_ct |= mask;
04882     edt_reg_write(edt_p, PDV_PLL_CTL, pll_ct);
04883     return (pll_ct);
04884 }
04885 
04886 u_char
04887 edt_clr_pllct_bit(EdtDev * edt_p, u_char mask)
04888 {
04889     u_char  pll_ct;
04890 
04891     pll_ct = edt_reg_read(edt_p, PDV_PLL_CTL);
04892     pll_ct &= ~mask;
04893     edt_reg_write(edt_p, PDV_PLL_CTL, pll_ct);
04894     return (pll_ct);
04895 }
04896 
04897 void
04898 edt_set_out_clk(EdtDev * edt_p, edt_pll * clk_data)
04899 {
04900     int use_pcd_method;
04901 
04902     unsigned char opt_e = 0;
04903     u_int   svfnct;
04904 
04905     if (ID_IS_PCD(edt_p->devid) || edt_p->devid == PDVAERO_ID)
04906         use_pcd_method = 1;
04907     else
04908         use_pcd_method = 0;
04909 
04910     switch (clk_data->h)
04911     {
04912     case 1:
04913         opt_e = EDT_FAST_DIV1;
04914         break;
04915 
04916     case 3:
04917         opt_e = EDT_FAST_DIV3;
04918         break;
04919 
04920     case 5:
04921         opt_e = EDT_FAST_DIV5;
04922         break;
04923 
04924     case 7:
04925         opt_e = EDT_FAST_DIV7;
04926         break;
04927 
04928     default:
04929         edt_msg(EDTDEBUG, "Illegal value %d for xilinx fast clk divide\n",
04930             clk_data->h);
04931         opt_e = EDT_FAST_DIV1;
04932         clk_data->h = 1;
04933         break;
04934     }
04935     opt_e |= ((clk_data->l - 1) << EDT_X_DIVN_SHFT);
04936 
04937 
04938     if (use_pcd_method)
04939     {
04940         edt_reg_write(edt_p, EDT_OUT_SCALE, opt_e);
04941         edt_reg_write(edt_p, EDT_REF_SCALE, clk_data->x - 1);
04942         svfnct = edt_reg_read(edt_p, PCD_FUNCT);
04943         edt_set_funct_bit(edt_p, EDT_FUNCT_SELAV);
04944         edt_clr_funct_bit(edt_p, EDT_FUNCT_CLK);
04945 
04946 
04947     }
04948     else
04949     {
04950         edt_reg_write(edt_p, PDV_OUT_SCALE, opt_e);
04951         edt_reg_write(edt_p, PDV_REF_SCALE, clk_data->x - 1);
04952         svfnct = edt_reg_read(edt_p, PDV_PLL_CTL);
04953         edt_set_pllct_bit(edt_p, EDT_FUNCT_SELAV);
04954         edt_clr_pllct_bit(edt_p, EDT_FUNCT_CLK);
04955 
04956     }
04957 
04958 
04959     svfnct &= ~EDT_FUNCT_SELAV;  /* Must turn this off when done - jerry */
04960 
04961     /* shift out data */
04962     shft_av9110(edt_p, clk_data->n, 7);
04963     shft_av9110(edt_p, clk_data->m, 7);
04964     /* set vco preescale */
04965     if (clk_data->v == 1)
04966         shft_av9110(edt_p, 0, 1);
04967     else
04968         shft_av9110(edt_p, 1, 1);
04969     /* clkx divide is not used (right now) so set to div 1 */
04970     switch (clk_data->r)
04971     {
04972     case 1:
04973         shft_av9110(edt_p, 0x170, 9);
04974         break;
04975 
04976     case 2:
04977         shft_av9110(edt_p, 0x174, 9);
04978         break;
04979 
04980     case 4:
04981         shft_av9110(edt_p, 0x178, 9);
04982         break;
04983 
04984     case 8:
04985         shft_av9110(edt_p, 0x17c, 9);
04986         break;
04987 
04988     default:
04989         edt_msg(EDTDEBUG, "illegal value %d for AV9110 aoutput divide\n",
04990             clk_data->r);
04991         shft_av9110(edt_p, 0x5c, 7);
04992         break;
04993     }
04994     /* restore fnct bits */
04995 
04996     if (use_pcd_method)
04997         edt_reg_write(edt_p, PCD_FUNCT, svfnct);
04998     else
04999         edt_reg_write(edt_p, PDV_PLL_CTL, svfnct);
05000 
05001 }
05002 
05003 u_int
05004 edt_set_sglist(EdtDev *edt_p,
05005                uint_t bufnum,
05006                uint_t *log_list,
05007                uint_t log_entrys)
05008 {
05009     int ret ;
05010     buf_args sg_args ;
05011     sg_args.index = bufnum ;
05012     sg_args.size = log_entrys ;
05013 #ifdef WIN32
05014     sg_args.addr = (uint64_t) (log_list);
05015 #else
05016     sg_args.addr = (uint64_t) ((unsigned long) log_list);
05017 #endif
05018     ret = edt_ioctl(edt_p, EDTS_SGLIST, &sg_args);
05019 
05020     return ret;
05021 }
05022 
05023 u_int
05024 edt_set_sgbuf(EdtDev * edt_p, u_int sgbuf, u_int bufsize, u_int bufdir, u_int verbose)
05025 {
05026     edt_set_buffer_size(edt_p, sgbuf, bufsize, bufdir) ;
05027     return 0;
05028 }
05029 
05046 int
05047 edt_set_timeout_action(EdtDev * edt_p, u_int action)
05048 
05049 {
05050 
05051     if (!edt_p)
05052     {
05053         return -1;
05054 
05055     }
05056 
05057     edt_ioctl(edt_p, EDTS_TIMEOUT_ACTION, &action);
05058 
05059     return 0;
05060 }
05061 
05075 int
05076 edt_get_timeout_goodbits(EdtDev * edt_p)
05077 
05078 {
05079 
05080     u_int   nGoodBits;
05081 
05082     if (!edt_p)
05083     {
05084         return 0;
05085     }
05086 
05087     edt_ioctl(edt_p, EDTG_TIMEOUT_GOODBITS, &nGoodBits);
05088 
05089     return nGoodBits;
05090 }
05091 
05105 int
05106 edt_get_goodbits(EdtDev * edt_p)
05107 
05108 {
05109 
05110     u_int   nGoodBits;
05111 
05112     if (!edt_p)
05113     {
05114         return 0;
05115     }
05116 
05117     edt_ioctl(edt_p, EDTG_GOODBITS, &nGoodBits);
05118 
05119     return nGoodBits;
05120 }
05121 
05226 #ifdef _NT_
05227 
05228 int
05229 edt_get_kernel_event(EdtDev *edt_p, int event_type)
05230 
05231 {
05232     EdtEventHandler *p;
05233     char    fullname[128];
05234     char   *Name;
05235     char *edt_devname;
05236 
05237     if (edt_p == NULL
05238         || (event_type < 0)
05239         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05240         || ((Name = BaseEventNames[event_type]) == NULL)
05241         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05242     {
05243         /* out of range */
05244         edt_msg(EDTDEBUG, "Invalid argument to edt_get_kernel_event\n");
05245         return -1;
05246     }
05247 
05248     /* device ID -> drivertype name string */
05249     if (edt_p->devid == P11W_ID)
05250         edt_devname = "P11w";
05251     else if (edt_p->devid == P16D_ID)
05252         edt_devname = "P16d";
05253     else if (edt_is_pcd(edt_p))
05254         edt_devname = "Pcd";
05255     else if (edt_is_pdv(edt_p))
05256         edt_devname = "Pdv";
05257     else if (edt_is_1553(edt_p))
05258         edt_devname = "P53b";
05259     else
05260     {
05261         edt_devname = NULL;
05262         edt_msg(EDTDEBUG, "Unknown device type %d\n", edt_p->devid);
05263         return -1;
05264     }
05265 
05266     sprintf(fullname, "%s%s%d%d", edt_devname, Name, edt_p->unit_no, edt_p->channel_no);
05267 
05268     if ((p->wait_event =
05269         CreateEvent(NULL, FALSE, FALSE,fullname)) == NULL)
05270     {
05271         if ((p->wait_event =
05272             OpenEvent(SYNCHRONIZE, FALSE, fullname)) == NULL)
05273         {
05274 
05275             edt_msg(EDTDEBUG, "Unable to open event %s\n", fullname);
05276             edt_msg_perror(EDTFATAL, "event") ;
05277 
05278             return -1;
05279 
05280         }
05281         else
05282         {
05283             ResetEvent(p->wait_event) ;
05284             return(0) ;
05285         }
05286 
05287     }
05288     else
05289     {
05290         edt_buf argbuf ;
05291         argbuf.desc = event_type ;
05292         argbuf.value = (uint64_t)p->wait_event ;
05293         edt_ioctl(edt_p, EDTS_EVENT_HNDL, &argbuf);
05294         ResetEvent(p->wait_event) ;
05295     }
05296 
05297     return 0;
05298 
05299 }
05300 
05301 /********************************************************
05302 * Close everything and zero memory
05303 ********************************************************/
05304 
05305 static
05306 void
05307 edt_clear_event_func(EdtEventHandler * p)
05308 
05309 {
05310     if (p->wait_thread)
05311         CloseHandle(p->wait_thread);
05312     if (p->wait_event)
05313         CloseHandle(p->wait_event);
05314     if (p->closing_event)
05315         CloseHandle(p->closing_event);
05316 
05317     memset(p, 0, sizeof(*p));
05318 
05319 }
05320 
05321 /********************************************************/
05322 /* Thread function to wait on a particular driver event */
05323 /********************************************************/
05324 
05325 static u_int WINAPI
05326 edt_wait_event_thread(void *pObj)
05327 {
05328     EdtEventHandler *p = (EdtEventHandler *) pObj;
05329     int     rc = WAIT_OBJECT_0;
05330     HANDLE  events[2];
05331     u_int   tmp;
05332 
05333 
05334     if (p)
05335     {
05336         events[0] = p->wait_event;
05337         events[1] = p->closing_event;
05338 
05339         while (p->active)
05340         {
05341 
05342 #ifndef NEW_WAY
05343             rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
05344 #else
05345 
05346             edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
05347 #endif
05348 
05349             if (p->active && rc == WAIT_OBJECT_0)
05350             {
05351                 edt_ioctl(p->owner, EDTS_CLR_EVENT, &p->event_type);
05352 
05353                 if (p->callback)
05354                     p->callback(p->data);
05355 
05356             }
05357 
05358             if (p->continuous == 0)
05359             {
05360                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
05361 
05362                 /* May need this later -- Mark 01/99 */
05363                 tmp = p->thrdid;
05364                 /*p->active = 0 ;*/
05365                 edt_clear_event_func(p);
05366                 p->thrdid = tmp;
05367 
05368                 break;
05369             }
05370         }
05371     }
05372     return 0;
05373 }
05374 
05375 /* ****************************************************** */
05376 /* Add an event function for an event_type               */
05377 /* Name is derived from event type -                     */
05378 /* only works for "base events" defined for all boards   */
05379 /* ****************************************************** */
05380 
05381 int
05382 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc func, void *data,
05383                    int continuous)
05384 {
05385     EdtEventHandler *p;
05386     char   *Name;
05387     HANDLE event;
05388 
05389     edt_msg(EDTDEBUG, "edt_set_event_func(type %d cont %d)\n", event_type, continuous);
05390 
05391     if (edt_p == NULL || (func == NULL)
05392         || (event_type < 0)
05393         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05394         || ((Name = BaseEventNames[event_type]) == NULL)
05395         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05396     {
05397         /* out of range */
05398         return -1;
05399     }
05400 
05401 
05402     if (p->callback)
05403     {
05404         /* whoops - we're already going */
05405 
05406         /* if it's the same callback, no problem */
05407 
05408         if (p->callback == func && p->data == data)
05409             return 0;
05410         else
05411             return -1;
05412     }
05413 
05414     /* Set the function */
05415     p->callback = func;
05416     /* Set the data */
05417     p->data = data;
05418 
05419     p->owner = edt_p;
05420     p->active = TRUE;
05421     p->event_type = event_type;
05422     p->continuous = continuous;
05423 
05424 
05425     /* Unlock */
05426 
05427     /* Launch the thread */
05428 
05429 
05430     edt_get_kernel_event(edt_p, event_type) ;
05431     event = edt_p->event_funcs[event_type].wait_event;
05432 
05433     if (event == NULL)
05434     {
05435         edt_clear_event_func(p);
05436         return -1;
05437 
05438     }
05439 
05440     if ((p->closing_event = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
05441     {
05442         edt_clear_event_func(p);
05443         return -1;
05444     }
05445 #ifdef __APPLE__
05446     if ((p->wait_thread = (mac_thread_t)
05447         _beginthreadex(NULL, 0, edt_wait_event_thread, p, CREATE_SUSPENDED,
05448         &p->thrdid)) == NULL)
05449 #else
05450     if ((p->wait_thread = (thread_t)
05451         _beginthreadex(NULL, 0, edt_wait_event_thread, p, CREATE_SUSPENDED,
05452         &p->thrdid)) == NULL)
05453 #endif
05454     {
05455         edt_clear_event_func(p);
05456         return -1;
05457     }
05458 
05459     /*
05460     * The continuous parameter now supports one of three modes:
05461     *
05462     *           EDT_EVENT_MODE_ONCE             (0)
05463     *           EDT_EVENT_MODE_CONTINUOUS       (1)
05464     *           EDT_EVENT_MODE_SERIALIZE        (2)
05465     *
05466     * The mode is passed to the driver in the high byte of event_type.
05467     */
05468     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
05469     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05470     event_type &= ~EDT_EVENT_MODE_MASK ;
05471 
05472     ResumeThread(p->wait_thread);
05473 
05474     /*SetThreadPriority(p->wait_thread, THREAD_PRIORITY_HIGHEST);*/
05475 
05476     return 0;
05477 }
05478 
05479 int
05480 edt_remove_event_func(EdtDev * edt_p, int event_type)
05481 
05482 {
05483     EdtEventHandler *p;
05484 
05485     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
05486     {
05487         /* out of range */
05488         return -1;
05489     }
05490 
05491     p = &edt_p->event_funcs[event_type];
05492 
05493     /*
05494     * Try and close the thread gracefully
05495     */
05496 
05497     if (p->wait_thread && p->wait_event)
05498     {
05499         p->active = FALSE;
05500 
05501         SetEvent(p->closing_event);
05502 
05503         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
05504 
05505         WaitForSingleObject(p->wait_thread, INFINITE);
05506 
05507         edt_clear_event_func(p);
05508 
05509     }else
05510         edt_clear_event_func(p);
05511 
05512     return 0;
05513 }
05514 
05515 #elif defined(__sun)            /* _NT_ */
05516 
05517 /* *******************************************************/
05518 /* Add an event function for an event_type               */
05519 /* Name is derived from event type                       */
05520 /* - only works for "base events" defined for all boards */
05521 /* *******************************************************/
05522 
05523 int
05524 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
05525                    int continuous)
05526 {
05527     EdtEventHandler *p;
05528     char    fullname[128];
05529     char   *Name;
05530 
05531 
05532     if (edt_p == NULL || (f == NULL)
05533         || (event_type < 0)
05534         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05535         || ((Name = BaseEventNames[event_type]) == NULL)
05536         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05537     {
05538         /* out of range */
05539         return -1;
05540     }
05541 
05542     if (p->active && p->callback)
05543     {
05544         /* whoops - we're already going */
05545         edt_remove_event_func(edt_p, event_type);
05546     }
05547     /*
05548     * Solaris:  if another thread has run for this event, wait for it.
05549     * Otherwise it stays alive and uses mmap() resources.  Mark  01/99
05550     */
05551     else if (p->thrdid)
05552         thr_join(p->thrdid, NULL, NULL);
05553 
05554     /* Set the function */
05555     p->callback = f;
05556     /* Set the data */
05557     p->data = data;
05558 
05559     p->owner = edt_p;
05560     p->active = TRUE;
05561     p->event_type = event_type;
05562     p->continuous = continuous;
05563 
05564     sema_init(&p->sema_thread, 0, USYNC_PROCESS, NULL);
05565 
05566     /*
05567     * The continuous parameter now supports one of three modes:
05568     *
05569     *           EDT_EVENT_MODE_ONCE             (0)
05570     *           EDT_EVENT_MODE_CONTINUOUS       (1)
05571     *           EDT_EVENT_MODE_SERIALIZE        (2)
05572     *
05573     * The mode is passed to the driver in the high byte of event_type.
05574     */
05575     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
05576     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05577     event_type &= ~EDT_EVENT_MODE_MASK ;
05578 
05579     /* Launch the thread */
05580 
05581     sprintf(fullname, "%s%d%d", Name, edt_p->unit_no, edt_p->channel_no);
05582     if (thr_create(NULL, 0, edt_wait_event_thread, (void *) p,
05583         THR_NEW_LWP | THR_BOUND, &p->thrdid))
05584     {
05585         edt_msg_perror(EDTFATAL, "edt_set_event_func: thr_create");
05586         edt_msg(EDTWARN, "Unable to create eventthread %s\n", fullname);
05587         edt_msg(EDTWARN, "thr_create:  use \"-lthread\" compile option\n", stderr);
05588         return -1;
05589     }
05590 
05591     sema_wait(&p->sema_thread);
05592     thr_yield();
05593 
05594     return 0;
05595 }
05596 
05597 /********************************************************/
05598 /* Close everything and zero memory                      */
05599 /********************************************************/
05600 
05601 static
05602 void
05603 edt_clear_event_func(EdtEventHandler * p)
05604 
05605 {
05606     /* TODO - anything else need to be done here for solaris?  -- Mark 01/99 */
05607     memset(p, 0, sizeof(*p));
05608 }
05609 
05610 
05611 /********************************************************/
05612 /* Thread function to wait on a particular driver event */
05613 /********************************************************/
05614 
05615 static void *
05616 edt_wait_event_thread(void *pObj)
05617 
05618 {
05619     EdtEventHandler *p = (EdtEventHandler *) pObj;
05620 #ifdef __APPLE__
05621     mac_thread_t;
05622 #else
05623     thread_t tmp;
05624 #endif
05625     int     ret;
05626 
05627 #ifdef __sun
05628     if (p->owner->use_RT_for_event_func)
05629         edt_set_RT(1) ;         /* This isn't a good idea unless
05630                             * you really can't live without it.  - Mark
05631                             */
05632 #endif
05633 
05634     if (p)
05635     {
05636         while (p->active)
05637         {
05638             sema_post(&p->sema_thread);
05639             if (p->continuous == 0)
05640                 edt_ioctl(p->owner, EDTS_WAIT_EVENT_ONCE, &p->event_type);
05641             else
05642                 edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
05643 
05644             if (p->active && p->callback)
05645                 p->callback(p->data);
05646 
05647             if (p->continuous == 0)
05648             {
05649                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
05650 
05651                 /* Need this later for thr_join() in set_event_func() */
05652                 tmp = p->thrdid;
05653                 edt_clear_event_func(p);
05654                 p->thrdid = tmp;
05655 
05656                 break;
05657             }
05658         }
05659     }
05660 
05661     thr_exit(NULL);
05662 
05663     return pObj;
05664 }
05665 
05666 /* *******************************************************/
05667 /* Delete an event handler                               */
05668 /* *******************************************************/
05669 
05670 int
05671 edt_remove_event_func(EdtDev * edt_p, int event_type)
05672 {
05673     EdtEventHandler *p;
05674 
05675     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
05676     {
05677         /* out of range */
05678         return -1;
05679     }
05680 
05681     p = &edt_p->event_funcs[event_type];
05682 
05683     /*
05684     * Try and close the thread gracefully
05685     */
05686 
05687     if (p->active)
05688     {
05689         p->active = FALSE;
05690 
05691         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
05692 
05693         thr_join(p->thrdid, NULL, NULL);
05694 
05695         edt_clear_event_func(p);
05696     }
05697 
05698     return 0;
05699 }
05700 #elif defined(sgi) || defined(__linux__) || defined(__APPLE__)
05701 
05702 #ifndef NO_PTHREAD
05703 
05704 #include <pthread.h>
05705 
05706 /* *******************************************************/
05707 /* Add an event function for an event_type               */
05708 /* Name is derived from event type                       */
05709 /* - only works for "base events" defined for all boards */
05710 /* *******************************************************/
05711 
05712 int
05713 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
05714                    int continuous)
05715 {
05716     EdtEventHandler *p;
05717     char    fullname[128];
05718     char   *Name;
05719 
05720 
05721     if (edt_p == NULL || (f == NULL)
05722         || (event_type < 0)
05723         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05724         || ((Name = BaseEventNames[event_type]) == NULL)
05725         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05726     {
05727         /* out of range */
05728         return -1;
05729     }
05730 
05731     if (p->active && p->callback)
05732     {
05733         /* whoops - we're already going */
05734         edt_remove_event_func(edt_p, event_type);
05735     }
05736     /*
05737     * pthreads:  if another thread has run for this event, wait for it.
05738     * Otherwise it stays alive and uses mmap() resources.  Mark  01/99
05739     */
05740     else if (p->thrdid)
05741         pthread_join(p->thrdid, NULL);
05742 
05743     /* Set the function */
05744     p->callback = f;
05745     /* Set the data */
05746     p->data = data;
05747 
05748     p->owner = edt_p;
05749     p->active = TRUE;
05750     p->event_type = event_type;
05751     p->continuous = continuous;
05752 
05753 
05754     /* sema_init(&p->sema_thread, 0, USYNC_PROCESS, NULL); */
05755 
05756     /*
05757     * The continuous parameter now supports one of three modes:
05758     *
05759     *           EDT_EVENT_MODE_ONCE             (0)
05760     *           EDT_EVENT_MODE_CONTINUOUS       (1)
05761     *           EDT_EVENT_MODE_SERIALIZE        (2)
05762     *
05763     * The mode is passed to the driver in the high byte of event_type.
05764     */
05765     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
05766     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05767     event_type &= ~EDT_EVENT_MODE_MASK ;
05768 
05769     /* Launch the thread */
05770 
05771     sprintf(fullname, "%s%d%d", Name, edt_p->unit_no, edt_p->channel_no);
05772     if (pthread_create(&p->thrdid, 0, edt_wait_event_thread, (void *) p)
05773         != 0)
05774     {
05775         edt_msg_perror(EDTFATAL, "edt_set_event_func: thr_create");
05776         edt_msg(EDTWARN, "Unable to create eventthread %s\n", fullname);
05777         edt_msg(EDTWARN, "thr_create:  use \"-lthread\" compile option\n", stderr);
05778         return -1;
05779     }
05780 
05781     /* sema_wait(&p->sema_thread); */
05782     /* thr_yield(); */
05783 
05784     return 0;
05785 }
05786 
05787 /********************************************************/
05788 /* Close everything and zero memory                      */
05789 /********************************************************/
05790 
05791 static
05792 void
05793 edt_clear_event_func(EdtEventHandler * p)
05794 
05795 {
05796     /* TODO - anything else need to be done here for solaris?  -- Mark 01/99 */
05797     memset(p, 0, sizeof(*p));
05798 }
05799 
05800 
05801 /********************************************************/
05802 /* Thread function to wait on a particular driver event */
05803 /********************************************************/
05804 
05805 static void *
05806 edt_wait_event_thread(void *pObj)
05807 
05808 {
05809     EdtEventHandler *p = (EdtEventHandler *) pObj;
05810     pthread_t tmp;
05811 
05812     if (p)
05813     {
05814         while (p->active)
05815         {
05816             /* sema_post(&p->sema_thread); */
05817             if (p->continuous == 0)
05818                 edt_ioctl(p->owner, EDTS_WAIT_EVENT_ONCE, &p->event_type);
05819             else
05820                 edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
05821 
05822             if (p->active && p->callback)
05823                 p->callback(p->data);
05824 
05825             if (p->continuous == 0)
05826             {
05827                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
05828 
05829                 /* Need this later for thr_join() in set_event_func() */
05830                 tmp = p->thrdid;
05831                 edt_clear_event_func(p);
05832                 p->thrdid = tmp;
05833 
05834                 break;
05835             }
05836         }
05837     }
05838 
05839     pthread_exit(NULL);
05840 
05841     return pObj;
05842 }
05843 
05844 /* *******************************************************/
05845 /* Delete an event handler                               */
05846 /* *******************************************************/
05847 
05848 int
05849 edt_remove_event_func(EdtDev * edt_p, int event_type)
05850 {
05851     EdtEventHandler *p;
05852 
05853     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
05854     {
05855         /* out of range */
05856         return -1;
05857     }
05858 
05859     p = &edt_p->event_funcs[event_type];
05860 
05861     /*
05862     * Try and close the thread gracefully
05863     */
05864 
05865     if (p->active)
05866     {
05867         p->active = FALSE;
05868 
05869         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
05870 
05871         pthread_join(p->thrdid, NULL);
05872 
05873         edt_clear_event_func(p);
05874     }
05875 
05876     return 0;
05877 }
05878 #endif   /* NOT PTHREAD */
05879 
05880 #elif defined(_AIX) || defined(__hpux)
05881 
05882 /* *******************************************************
05883 * Add an event function for an event_type
05884 * Name is derived from event type - only works
05885 * for "base events" defined for all boards
05886 * *******************************************************/
05887 
05888 int
05889 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
05890                    int continuous)
05891 {
05892     return -1;
05893 }
05894 
05895 /********************************************************
05896 * Close everything and zero memory
05897 ********************************************************/
05898 
05899 static
05900 void
05901 edt_clear_event_func(EdtEventHandler * p)
05902 
05903 {
05904 
05905 }
05906 
05907 
05908 /********************************************************
05909 * Thread function to wait on a particular driver event *
05910 ********************************************************/
05911 
05912 static void *
05913 edt_wait_event_thread(void *pObj)
05914 
05915 {
05916     return NULL;
05917 }
05918 
05919 /* *******************************************************
05920 * Delete an event handler                                                               *
05921 * *******************************************************/
05922 
05923 int
05924 edt_remove_event_func(EdtDev * edt_p, int event_type)
05925 {
05926     return -1;
05927 }
05928 
05929 #else
05930 
05931 int
05932 edt_remove_event_func(EdtDev * edt_p, int event_type)
05933 {
05934     return -1;
05935 }
05936 
05937 #endif                          /* _NT_ */
05938 
05939 int
05940 edt_enable_event(EdtDev * edt_p, int event_type)
05941 {
05942     edt_msg(EDTDEBUG, "edt_enable_event(type %d)\n", event_type) ;
05943 
05944     if (edt_p == NULL
05945         || (event_type < 0)
05946         || (event_type >= EDT_MAX_KERNEL_EVENTS))
05947     {
05948         /* out of range */
05949         return -1;
05950     }
05951 
05952 #ifdef _NT_
05953     edt_get_kernel_event(edt_p, event_type) ;
05954 #endif
05955 
05956     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05957 
05958     return 0 ;
05959 }
05960 
05961 int
05962 edt_wait_event(EdtDev * edt_p, int event_type, int timeoutval)
05963 {
05964     int ret = 0 ;
05965     edt_msg(EDTDEBUG, "edt_wait_event(type %d)\n", event_type) ;
05966 #ifdef _NT_
05967     {
05968         HANDLE event;
05969         int rc;
05970 
05971         if (!edt_p->event_funcs[event_type].wait_event)
05972         {
05973             edt_get_kernel_event(edt_p, event_type);
05974         }
05975 
05976         event = edt_p->event_funcs[event_type].wait_event;
05977 
05978         /* wait for event */
05979 
05980         if (timeoutval == 0)
05981             timeoutval = INFINITE;
05982 
05983         rc = WaitForSingleObject(event, timeoutval);
05984 
05985         if (rc == WAIT_TIMEOUT)
05986         {
05987             /* edt_msg(EDTDEBUG, "timeout...\n");*/
05988 
05989             /* deal with timeout */
05990 
05991             edt_do_timeout(edt_p);
05992 
05993             ret = 1 ;
05994         }
05995     }
05996 #else
05997     edt_ioctl(edt_p, EDTS_WAIT_EVENT, &event_type);
05998 #endif
05999 
06000     edt_msg(EDTDEBUG, "edt_wait_event(type %d)\n", event_type, ret) ;
06001 
06002     return(ret) ;
06003 }
06004 
06005 
06010 int
06011 edt_reset_event_counter(EdtDev * edt_p, int event_type)
06012 {
06013     return edt_ioctl(edt_p, EDTS_RESET_EVENT_COUNTER, &event_type);
06014 }
06015 
06016 
06017 
06029 int
06030 edt_stop_buffers(EdtDev * edt_p)
06031 
06032 {
06033     unsigned int finish_current = 1;
06034 
06035     edt_msg(EDTDEBUG, "edt_stop_buffers\n");
06036     edt_ioctl(edt_p, EDTS_STOPBUF, &finish_current);
06037     return 0;
06038 }
06039 
06056 int
06057 edt_reset_ring_buffers(EdtDev * edt_p, uint_t bufnum)
06058 
06059 {
06060     bufcnt_t     curdone;
06061     int     curBufIndex = -1;
06062 
06063     curdone = edt_done_count(edt_p);
06064     edt_cancel_current_dma(edt_p);
06065     if (edt_p->ring_buffer_numbufs)
06066     {
06067         curBufIndex = curdone % edt_p->ring_buffer_numbufs;
06068         edt_set_buffer(edt_p, bufnum);
06069     }
06070     edt_msg(EDTDEBUG, "edt_reset_ring_buffers buf %d curdone %d curBufIndex %d\n",
06071         bufnum, curdone, curBufIndex);
06072     return 0;
06073 }
06074 
06088 int
06089 edt_abort_dma(EdtDev * edt_p)
06090 
06091 {
06092     edt_msg(EDTDEBUG, "edt_abort_dma\n");
06093     edt_reset_ring_buffers(edt_p, edt_done_count(edt_p));
06094     return 0;
06095 }
06096 
06110 int
06111 edt_abort_current_dma(EdtDev * edt_p)
06112 
06113 {
06114     edt_msg(EDTDEBUG, "edt_abort_current_dma\n");
06115     edt_reset_ring_buffers(edt_p, edt_done_count(edt_p) + 1);
06116     return 0;
06117 }
06118 
06129 int
06130 edt_ring_buffer_overrun(EdtDev *edt_p)
06131 
06132 {
06133     bufcnt_t   dmacount;
06134 
06135     dmacount = edt_done_count(edt_p);
06136 
06137     if (dmacount >= edt_p->donecount + edt_p->ring_buffer_numbufs)
06138         return (1);
06139     else
06140         return (0);
06141 }
06142 
06143 
06144 #ifdef P16D
06145 
06156 u_short
06157 p16d_get_command(EdtDev * edt_p)
06158 {
06159     return (edt_reg_read(edt_p, P16_COMMAND));
06160 }
06161 
06173 void
06174 p16d_set_command(EdtDev * edt_p, u_short val)
06175 {
06176     edt_reg_write(edt_p, P16_COMMAND, val);
06177 }
06178 
06189 u_short
06190 p16d_get_config(EdtDev * edt_p)
06191 {
06192     return (edt_reg_read(edt_p, P16_CONFIG));
06193 }
06194 
06206 void
06207 p16d_set_config(EdtDev * edt_p, u_short val)
06208 {
06209     edt_reg_write(edt_p, P16_CONFIG, val);
06210 }
06211 
06222 u_short
06223 p16d_get_stat(EdtDev * edt_p)
06224 {
06225     return (edt_reg_read(edt_p, P16_STATUS));
06226 }
06227 
06228 #endif                          /* P16D */
06229 
06230 
06246 int
06247 edt_parse_unit_channel(const char *instr,
06248                        char *dev,
06249                        const char *default_dev,
06250                        int *channel_ptr)
06251 {
06252     int     unit = -1;
06253     int         channel = -1;
06254     size_t              last;
06255 
06256     char    retdev[256];
06257     char    str[256];
06258 
06259 
06260     edt_msg(EDTDEBUG, "edt_parse_unit_channel %s dev %s default %s: ",
06261         instr, dev, default_dev);
06262 
06263     if (default_dev)
06264         strcpy(retdev, default_dev);
06265     else
06266         strcpy(retdev, EDT_INTERFACE);
06267 
06268     strcpy(str,instr);
06269 
06270     if (strlen(str))
06271     {
06272         last = strlen(str)-1;
06273 
06274         /* find the channel or unit */
06275 
06276         if (isdigit(str[last]))
06277         {
06278             while (last && isdigit(str[last]))
06279             {
06280                 last--;
06281             }
06282 
06283             if (!isdigit(str[last]))
06284             {
06285                 last++;
06286             }
06287 
06288             channel = atoi(str+last);
06289 
06290             if (str[0] != '/' && str[0] != '\\')
06291                 str[last] = 0;
06292 
06293             if (last>0)
06294                 last--;
06295 
06296             if (last && str[last] == '_')
06297             {
06298 
06299                 last--;
06300 
06301                 if (isdigit(str[last]))
06302                 {
06303                     size_t enddigit = last;
06304                     char checkstr[80];
06305 
06306                     while (last && isdigit(str[last]))
06307                     {
06308                         last--;
06309                     }
06310 
06311                     if (!isdigit(str[last]))
06312                     {
06313                         last++;
06314                     }
06315 
06316                     strncpy(checkstr,str+last,(enddigit - last)+1);
06317 
06318                     unit = atoi(checkstr);
06319 
06320                     if (str[0] != '/' && str[0] != '\\')
06321                         str[last] = 0;
06322 
06323                 }
06324                 else
06325                 {
06326                     unit = channel;
06327                     channel = -1;
06328                 }
06329             }
06330             else
06331             {
06332                 unit = channel;
06333                 channel = -1;
06334             }
06335 
06336         }
06337         else
06338             unit = 0;
06339     }
06340     else
06341         unit = 0;
06342 
06343     if (dev)
06344     {
06345         if (str[0])
06346             strcpy(dev, str);
06347         else
06348             strcpy(dev, retdev);
06349     }
06350 
06351     if (channel_ptr && (channel != -1))
06352         *channel_ptr = channel;
06353 
06354     return (unit);
06355 }
06356 
06385 int
06386 edt_parse_unit(const char *str, char *dev, const char *default_dev)
06387 {
06388     int channel = 0;
06389 
06390     return edt_parse_unit_channel(str,dev,default_dev, &channel);
06391 
06392 
06393 }
06394 int
06395 edt_serial_wait(EdtDev * edt_p, int msecs, int count)
06396 {
06397     edt_buf tmp;
06398     int     ret;
06399 
06400     tmp.desc = msecs;
06401     tmp.value = count;
06402     edt_ioctl(edt_p, EDTS_SERIALWAIT, &tmp);
06403     ret = (u_int) tmp.value;
06404 
06405     edt_msg(EDTDEBUG, "edt_serial_wait(%d, %d) %d\n", msecs, count, ret);
06406     return (ret);
06407 }
06408 
06442 int
06443 edt_ref_tmstamp(EdtDev *edt_p, u_int val)
06444 
06445 {
06446     return edt_ioctl(edt_p,EDTS_REFTMSTAMP,&val);
06447 
06448 }
06449 
06465 uint_t
06466 edt_get_bufbytecount(EdtDev * edt_p, u_int *cur_buffer)
06467 {
06468     uint_t args[2] ;
06469 
06470     if (edt_ioctl(edt_p, EDTG_BUFBYTECOUNT, &args) < 0)
06471         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_BUFBYTECOUNT)");
06472 
06473     if (cur_buffer)
06474         *cur_buffer = args[1] ;
06475     return (args[0]);
06476 }
06477 
06478 
06479 void
06480 edt_dmasync_fordev(EdtDev *edt, int bufnum, int offset, int bytecount)
06481 {
06482     u_int args[3] ;
06483 
06484     args[0] = bufnum ;
06485     args[1] = offset ;
06486     args[2] = bytecount ;
06487 
06488     edt_ioctl(edt, EDTS_DMASYNC_FORDEV, args) ;
06489 }
06490 
06491 void
06492 edt_dmasync_forcpu(EdtDev *edt, int bufnum, int offset, int bytecount)
06493 {
06494     u_int args[3] ;
06495 
06496     args[0] = bufnum ;
06497     args[1] = offset ;
06498     args[2] = bytecount ;
06499 
06500     edt_ioctl(edt, EDTS_DMASYNC_FORCPU, args) ;
06501 }
06502 
06503 /* return true if machine is little_endian */
06504 int
06505 edt_little_endian()
06506 {
06507     u_short test;
06508     u_char *byte_p;
06509 
06510     byte_p = (u_char *) & test;
06511     *byte_p++ = 0x11;
06512     *byte_p = 0x22;
06513     if (test == 0x1122)
06514     {
06515         edt_msg(EDTDEBUG, "edt_endian: BIG (SPARC, PowerPC)\n");
06516         return (0);
06517     }
06518     else
06519     {
06520         edt_msg(EDTDEBUG, "edt_endian: LITTLE (X86, AMD, SPARCv9)\n");
06521         return (1);
06522     }
06523 }
06524 
06525 
06526 //
06527 // Internal EDT lab use only - set all ring buffer SgList entries to specified 32-bit physaddr
06528 //
06529 int
06530 edt_set_buffer_physaddr(EdtDev * edt_p, uint_t index, uint64_t physaddr)
06531 {
06532 
06533     buf_args sysargs;
06534 
06535 
06536     if (edt_p->ring_buffers[index])
06537     {
06538 
06539         sysargs.index = index;
06540         sysargs.addr = physaddr;
06541         sysargs.size = 0;
06542 
06543         return edt_ioctl(edt_p, EDTS_BUF, &sysargs);
06544 
06545     }
06546     else
06547     {
06548 
06549         edt_msg_perror(EDTFATAL,
06550                 "edt_set_buffer_physaddr: Attempt to set physaddr on unallocated buffer\n");
06551 
06552         return -1;
06553 
06554     }
06555 
06556 }
06557 
06558 
06591 int
06592 edt_set_buffer_size(EdtDev * edt_p, uint_t index, uint_t size, uint_t write_flag)
06593 
06594 {
06595 
06596     buf_args sysargs;
06597 
06598     if (edt_p->ring_buffers[index])
06599     {
06600         if (size > (u_int) edt_p->rb_control[index].allocated_size)
06601         {
06602             edt_msg_perror(EDTFATAL, "edt_set_buffer_size: Attempt to set size greater than allocated\n");
06603             return -1;
06604         }
06605 
06606         edt_p->rb_control[index].size = size;
06607         sysargs.index = index;
06608         sysargs.writeflag = write_flag;
06609         sysargs.addr = 0;
06610         sysargs.size = size;
06611 
06612         return edt_ioctl(edt_p, EDTS_BUF, &sysargs);
06613 
06614     }
06615     else
06616     {
06617         edt_msg_perror(EDTFATAL, "edt_set_buffer_size: Attempt to set size on unallocated buffer\n");
06618 
06619         return -1;
06620     }
06621 }
06622 
06639 int
06640 edt_set_max_buffers(EdtDev *edt_p, int newmax)
06641 
06642 {
06643     edt_msg(EDTDEBUG, "edt_set_max_buffers\n");
06644 
06645     return
06646         edt_ioctl(edt_p, EDTS_MAX_BUFFERS, &newmax);
06647 }
06648 
06662 int
06663 edt_get_max_buffers(EdtDev *edt_p)
06664 
06665 {
06666     u_int val;
06667 
06668     if (edt_p->devid == DMY_ID) val = MAX_DMA_BUFFERS ;
06669     else edt_ioctl(edt_p, EDTG_MAX_BUFFERS, &val);
06670 
06671     return val;
06672 
06673 }
06674 
06675 
06676 void
06677 edt_resume(EdtDev * edt_p)
06678 {
06679     u_int dmy ;
06680 
06681     edt_msg(EDTDEBUG, "edt_resume\n") ;
06682     edt_ioctl(edt_p, EDTS_RESUME, &dmy);
06683 }
06684 
06709 uint_t
06710 edt_get_todo(EdtDev * edt_p)
06711 {
06712     u_int todo ;
06713     if (edt_p->devid == DMY_ID)
06714         todo = dmy_started ;
06715     else
06716         edt_ioctl(edt_p, EDTG_TODO, &todo);
06717     edt_msg(EDTDEBUG, "edt_get_todo: %d\n",todo) ;
06718     return todo;
06719 }
06720 
06721 uint_t
06722 edt_get_drivertype(EdtDev * edt_p)
06723 {
06724     u_int type ;
06725     edt_ioctl(edt_p, EDTG_DRIVER_TYPE, &type);
06726     edt_msg(EDTDEBUG, "edt_get_drivertype: %x\n",type) ;
06727     return type;
06728 }
06729 
06730 /* only for testing */
06731 int
06732 edt_set_drivertype(EdtDev *edt_p, u_int type)
06733 {
06734     edt_msg(EDTDEBUG, "edt_set_drivertype\n");
06735     return edt_ioctl(edt_p, EDTS_DRIVER_TYPE, &type);
06736 }
06737 
06761 int
06762 edt_get_reftime(EdtDev * edt_p, u_int * timep)
06763 {
06764     /* we return sec and nsec - change to usec */
06765     u_int   timevals[2];
06766 
06767     edt_ioctl(edt_p, EDTG_REFTIME, &timevals[0]);
06768     edt_msg(EDTDEBUG, "%x %x ",
06769         timevals[0],
06770         timevals[1]) ;
06771     timep[0] = timevals[0];
06772     timep[1] = timevals[1];
06773     return (timevals[1]) ;
06774 }
06775 
06776 void
06777 edt_set_timetype(EdtDev * edt_p, u_int type)
06778 {
06779     edt_ioctl(edt_p, EDTS_TIMETYPE, &type);
06780 }
06781 
06782 void
06783 edt_set_abortintr(EdtDev * edt_p, u_int val)
06784 {
06785     edt_ioctl(edt_p, EDTS_ABORTINTR, &val);
06786 }
06787 
06788 
06789 caddr_t
06790 edt_mapmem(EdtDev *edt_p, u_int addr, int size)
06791 {
06792     caddr_t     ret;
06793 #if defined(_NT_)
06794     edt_buf tmp;
06795 
06796     tmp.value = size;
06797     tmp.desc = addr;
06798 
06799     edt_ioctl(edt_p, EDTS_MAPMEM, &tmp);
06800 
06801     ret = (caddr_t) tmp.value ;
06802     edt_msg(EDTDEBUG, "edt_mapmem(%x, %x) %x %x\n", addr, size, tmp.desc,tmp.value);
06803     return (ret);
06804 
06805 #elif defined(__APPLE__)
06806 
06807     /* KLUDGE PCI device is already mapped to address 0
06808      * See EdtPciDriver.cpp start function
06809      */
06810     return (addr);
06811 
06812 
06813 #else
06814     ret = (caddr_t) mmap((caddr_t)0, size, PROT_READ|PROT_WRITE,
06815         MAP_SHARED, edt_p->fd, addr);
06816     if (ret == ((caddr_t)-1)) {
06817         perror("mmap call");
06818         return(0) ;
06819     }
06820     return(ret) ;
06821 #endif
06822 }
06823 
06824 u_int edt_get_mappable_size(EdtDev *edt_p, int bar /* Base Address Range, currently 0 or 1 */)
06825 
06826 {
06827     u_int value = 0;
06828 
06829     if (bar == 1)
06830         edt_ioctl(edt_p, EDTG_MEM2SIZE, &value);
06831     else
06832         edt_ioctl(edt_p, EDTG_MEMSIZE, &value);
06833 
06834     return value;
06835 
06836 }
06837 
06838 
06839 #ifdef __sun
06840 
06846 static id_t
06847 schedinfo(char *name, short *maxpri)
06848 {
06849     pcinfo_t info;
06850     tsinfo_t *tsinfop;
06851     rtinfo_t *rtinfop;
06852 
06853     (void) strcpy(info.pc_clname, name);
06854     if (priocntl(0L, 0L, PC_GETCID, (char *) &info) == -1L)
06855     {
06856         return (-1);
06857     }
06858     if (strcmp(name, "TS") == 0)
06859     {
06860         tsinfop = (struct tsinfo *) info.pc_clinfo;
06861         *maxpri = tsinfop->ts_maxupri;
06862     }
06863     else if (strcmp(name, "RT") == 0)
06864     {
06865         rtinfop = (struct rtinfo *) info.pc_clinfo;
06866         *maxpri = rtinfop->rt_maxpri;
06867     }
06868     else
06869     {
06870         return (-1);
06871     }
06872     return (info.pc_cid);
06873 }
06874 
06879 void
06880 edt_set_RT(u_int pri)
06881 {
06882     pcparms_t pcparms;
06883     rtparms_t *rtparmsp;
06884     id_t    rtID;
06885     short   maxrtpri;
06886 
06887     /* Get highest valid RT priority. */
06888     if ((rtID = schedinfo("RT", &maxrtpri)) == -1)
06889     {
06890         edt_msg_perror(EDTFATAL, "schedinfo failed for RT");
06891         exit(2);
06892     }
06893 
06894     /* Change proc to RT, highest prio - 1, default time slice */
06895     pcparms.pc_cid = rtID;
06896     rtparmsp = (struct rtparms *) pcparms.pc_clparms;
06897     rtparmsp->rt_pri = maxrtpri - (1 + pri) ;
06898     rtparmsp->rt_tqnsecs = RT_TQDEF;
06899 
06900     if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, (char *) &pcparms) == -1)
06901     {
06902         edt_msg_perror(EDTFATAL, "PC_SETPARMS failed");
06903         exit(3);
06904     }
06905 }
06906 #endif /* __sun */
06907 
06908 
06909 #ifdef PCD
06910 /*
06911 * SSE (fast serial) support.
06912 */
06913 
06914 /* These bits are in hi word of long, must split into two to do AND's, OR's */
06915 #define XPLLBYP (0x1<<17)
06916 #define XPLLCLK (0x1<<18)
06917 #define XPLLDAT (0x1<<19)
06918 #define XPLLSTB (0x1<<20)
06919 
06920 #define XC_X16  (0x00)          /* PC Only: hi for SCLK=16MHz, not SCLK=CCLK */
06921 #define XC_AVSEL (0x80)         /* GP Only: hi for SCLK=AVCLK, not SCLK=16MHz*/
06922 
06923 #define XC_CCLK (0x01)          /* These codes interpreted by sse_wpp() */
06924 #define XC_DIN  (0x02)          /*  Xilinx config data and clock */
06925 #define XC_PROG (0x04)          /*  inverted in sse_wpp() when driving PROGL */
06926 #define XC_INITL (0x04)         /* Actual bit positions in status register */
06927 #define XC_DONE  (0x08)
06928 
06929 /* Write encoded data to parallel port data register */
06930 static void
06931 sse_wpp(EdtDev *edt_p, int val)
06932 {
06933     unsigned char bits;
06934 
06935     bits = edt_intfc_read(edt_p, PCD_FUNCT) & 0x08;     /* Preserve SWAPEND */
06936 
06937     if (val & XC_DIN)   bits |= 0x04;
06938     if (val & XC_PROG)  bits |= 0x01;
06939     if (val & XC_AVSEL) bits |= 0x80;
06940 
06941     edt_intfc_write(edt_p, PCD_FUNCT, bits);
06942 
06943     if (val & XC_CCLK)          /* strobe the clock hi then low */
06944     {
06945         edt_intfc_write(edt_p, PCD_FUNCT, (unsigned char) (bits | 0x02));
06946         edt_intfc_write(edt_p, PCD_FUNCT, bits);
06947     }
06948 
06949     edt_msg(EDTDEBUG, "sse_wpp(%02x)  ", bits);
06950 }
06951 
06952 
06953 static int
06954 sse_spal(EdtDev * edt_p, int v)
06955 {
06956     edt_msleep(1);
06957     edt_intfc_write(edt_p, PCD_PAL0, (unsigned char) (v >> 0));
06958     edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (v >> 8));
06959     edt_intfc_write(edt_p, PCD_PAL2, (unsigned char) (v >> 16));
06960 
06961     return (edt_intfc_read(edt_p, PCD_PAL3));
06962 }
06963 
06964 static void
06965 sse_xosc(EdtDev * edt_p, int val)
06966 {
06967     int     n, s;       /* First set up MC12430 lines, CLK=0, DAT=0, STB=0 */
06968     int   gspv = edt_intfc_read(edt_p, PCD_PAL0)
06969         | edt_intfc_read(edt_p, PCD_PAL1) << 8
06970         | edt_intfc_read(edt_p, PCD_PAL2) << 16;
06971 
06972     gspv = (gspv & ~XPLLBYP & ~XPLLCLK & ~XPLLDAT & ~XPLLSTB);
06973     sse_wpp(edt_p, 0);
06974 
06975     edt_msleep(1);              /* Shut down AVSEL */
06976 
06977     for (n = 13; n >= 0; n--)
06978     {                           /* Send 14 bits of data to MC12430 */
06979         s = val & (0x1 << n);   /* get the current data bit */
06980 
06981         if (s)
06982         {
06983             sse_spal(edt_p, gspv | XPLLDAT);    /* Set up data, then clock it */
06984             sse_spal(edt_p, gspv | XPLLDAT | XPLLCLK);
06985         }
06986         else
06987         {
06988             sse_spal(edt_p, gspv);      /* Strobe clock only, no data */
06989             sse_spal(edt_p, gspv | XPLLCLK);
06990         }
06991 
06992         edt_msg(EDTDEBUG, "sse_xosc:  n:%d  s:%x\n", n, (s != 0));
06993     }
06994 
06995     sse_spal(edt_p, gspv | XPLLSTB);    /* Strobe serial_load */
06996     sse_spal(edt_p, gspv);              /* Clear the strobe */
06997 
06998 
06999     if ((val >> 11) == 6)
07000     {
07001         gspv |= XPLLBYP;
07002         sse_spal(edt_p, gspv);
07003 
07004         sse_wpp(edt_p, XC_AVSEL);       /* On GP, drive SCLK from AV9110 */
07005     }
07006     else
07007         sse_wpp(edt_p, 0);
07008 
07009 
07010     if (XC_X16)
07011         sse_wpp(edt_p, XC_X16);         /* On PC, drive SCLK with 16 MHz ref */
07012 }
07013 
07014 
07015 double
07016 sse_set_out_clk(EdtDev * edt_p, double fmhz)
07017 {                               /* Set ECL clock to freq specified in MHz */
07018     int     m, n, t, hex, nn, fx;
07019     edt_pll avp;
07020     double  avf = 0.0; /* should this have a more reasonable value? --doug */
07021 
07022     if (fmhz < 0)
07023     {
07024         printf("sse_set_pll_freq: Invalid argument %f\n", fmhz);
07025         return 0;
07026     }
07027 
07028     fx = (int) fmhz;
07029 
07030     if ((fmhz > 800.0) || (fmhz < 0.000050))
07031     {
07032         printf("Error, %f MHz requested.  Min of 0.000050, max of 800Mhz\n",
07033             fmhz);
07034         return (0);
07035     }
07036     else if (fx > 400)
07037     {
07038         t = 0;
07039         n = 3;
07040         m = fx / 2;
07041         nn = 1;
07042     }                           /* Every 2 MHz */
07043     else if (fx > 200)
07044     {
07045         t = 0;
07046         n = 0;
07047         m = fx;
07048         nn = 2;
07049     }                           /* Every 1 MHz */
07050     else if (fx > 100)
07051     {
07052         t = 0;
07053         n = 1;
07054         m = fx * 2;
07055         nn = 4;
07056     }                           /* Every 500 KHz */
07057     else if (fx >= 50)
07058     {
07059         t = 0;
07060         n = 2;
07061         m = fx * 4;
07062         nn = 8;
07063     }                           /* Every 250 KHz */
07064     else
07065     {
07066         avf = edt_find_vco_frequency(edt_p, fmhz * 1E6, (double) 30E6, &avp, 0);
07067         if (avf != 0)
07068             edt_set_out_clk(edt_p, &avp);       /* Load AV9110 */
07069         t = 6;
07070         n = 3;
07071         m = 200;
07072         nn = 4;                 /* Put MC12430 in bypass, use AV9110 */
07073     }
07074 
07075     hex = (t << 11) | (n << 9) | m;
07076 
07077     sse_xosc(edt_p, hex);       /* Load MC12430 hw */
07078 
07079     if (t != 6)
07080     {
07081         edt_msg(EDTDEBUG,
07082             "sse_set_out_clk:  %f MHz  MC12430: t:%d  n:%d  m:%d  hex:0x%04x\n",
07083             (2.0 * m / nn), t, n, m, hex);
07084         return (2.0 * m / nn);  /* Freq of MC12430 in MHz */
07085     }
07086     else
07087     {
07088         edt_msg(EDTDEBUG,
07089             "sse_set_out_clk: %f MHz AV9110:  m:%d n:%d v:%d r:%d h:%d l:%d x:%d\n",
07090             (avf / 1E6), avp.m, avp.n, avp.v, avp.r, avp.h, avp.l, avp.x);
07091         return (avf / 1E6);     /* Freq of AV9110 in MHz */
07092     }
07093 }
07094 
07095 
07096 
07097 
07098 void
07099 sse_shift(EdtDev *edt_p, int shift)
07100 {
07101     int n ;
07102     unsigned char  old;
07103 
07104     if (shift)
07105     {
07106         old = edt_intfc_read(edt_p, PCD_PAL1) & ~0x02;
07107         edt_intfc_write(edt_p, PCD_PAL1, old);
07108 
07109         for (n = 0; n < shift; n++)
07110         {
07111             edt_msleep(1);
07112             edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (0x02 | old));
07113             edt_msleep(1);
07114             edt_intfc_write(edt_p, PCD_PAL1, old);
07115         }
07116     }
07117 }
07118 /*
07119 To swallow a clock on channel 0, strobe bit 9,  so PCD_PAL1 0x02
07120 To swallow a clock on channel 1, strobe bit 21, so PCD_PAL2 0x20
07121 */
07122 void
07123 sse_shift_chan(EdtDev *edt_p, int shift, int channel)
07124 {
07125     int n ;
07126     unsigned char  old;
07127 
07128     if (shift) {
07129         if (channel==0) {
07130             old = edt_intfc_read(edt_p, PCD_PAL1) & ~0x02;
07131             edt_intfc_write(edt_p, PCD_PAL1, old);
07132 
07133             for (n = 0; n < shift; n++)
07134             {
07135                 edt_msleep(1);
07136                 edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (0x02 | old));
07137                 edt_msleep(1);
07138                 edt_intfc_write(edt_p, PCD_PAL1, old);
07139             }
07140         } else {
07141             old = edt_intfc_read(edt_p, PCD_PAL2) & ~0x20;
07142             edt_intfc_write(edt_p, PCD_PAL2, old);
07143 
07144             for (n = 0; n < shift; n++)
07145             {
07146                 edt_msleep(1);
07147                 edt_intfc_write(edt_p, PCD_PAL2, (unsigned char) (0x20 | old));
07148                 edt_msleep(1);
07149                 edt_intfc_write(edt_p, PCD_PAL2, old);
07150             }
07151         }
07152     }
07153 }
07154 #endif /* PCD */
07155 
07156 
07157 #ifdef P11W
07158 
07159 #include "p11w.h"
07160 
07161 u_short
07162 p11w_get_command(EdtDev * edt_p)
07163 {
07164     return (edt_reg_read(edt_p, P11_COMMAND));
07165 }
07166 
07167 void
07168 p11w_set_command(EdtDev * edt_p, u_short val)
07169 {
07170     edt_reg_write(edt_p, P11_COMMAND, val);
07171 }
07172 
07173 u_short
07174 p11w_get_config(EdtDev * edt_p)
07175 {
07176     return (edt_reg_read(edt_p, P11_CONFIG));
07177 }
07178 
07179 void
07180 p11w_set_config(EdtDev * edt_p, u_short val)
07181 {
07182     edt_reg_write(edt_p, P11_CONFIG, val);
07183 }
07184 
07185 u_short
07186 p11w_get_data(EdtDev * edt_p)
07187 {
07188     return (edt_reg_read(edt_p, P11_DATA));
07189 }
07190 
07191 void
07192 p11w_set_data(EdtDev * edt_p, u_short val)
07193 {
07194     edt_reg_write(edt_p, P11_DATA, val);
07195 }
07196 
07197 u_short
07198 p11w_get_stat(EdtDev * edt_p)
07199 {
07200     return (edt_reg_read(edt_p, P11_STATUS));
07201 }
07202 
07203 u_int
07204 p11w_get_count(EdtDev * edt_p)
07205 {
07206     return (edt_reg_read(edt_p, P11_COUNT));
07207 }
07208 
07209 /*
07210 * The following routine is deprecated.  Use the one following
07211 * this, p11w_set_abortdma_onintr().     Mark  6/04
07212 */
07213 void
07214 p11w_abortdma_onattn(EdtDev *edt_p, int flag)
07215 {
07216     int arg = 0x11 ;
07217     u_short readcmd ;
07218 
07219 
07220     if (flag)
07221     {
07222         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07223         readcmd |= P11W_EN_ATT ;
07224         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07225 
07226         edt_ioctl(edt_p, EDTS_CUSTOMER, &arg) ;
07227     }
07228     else
07229     {
07230         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07231         readcmd &= ~P11W_EN_ATT ;
07232         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07233 
07234         arg = 0 ;
07235         edt_ioctl(edt_p, EDTS_CUSTOMER, &arg) ;
07236     }
07237 }
07238 
07239 void
07240 p11w_set_abortdma_onintr(EdtDev *edt_p, int flag)
07241 {
07242     u_short readcmd, writecmd ;
07243 
07244     if (flag == 0)
07245     {
07246         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07247         readcmd &= ~P11W_EN_ATT ;
07248         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07249 
07250         edt_ioctl(edt_p, P11G_WRITE_COMMAND, &writecmd) ;
07251         writecmd &= ~P11W_EN_ATT ;
07252         edt_ioctl(edt_p, P11S_WRITE_COMMAND, &writecmd) ;
07253     }
07254 
07255     edt_ioctl(edt_p, EDTS_ABORTDMA_ONINTR, &flag) ;
07256 
07257     if (flag)
07258     {
07259         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07260         readcmd |= P11W_EN_ATT ;
07261         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07262 
07263         edt_ioctl(edt_p, P11G_WRITE_COMMAND, &writecmd) ;
07264         writecmd |= P11W_EN_ATT ;
07265         edt_ioctl(edt_p, P11S_WRITE_COMMAND, &writecmd) ;
07266     }
07267 }
07268 
07269 #endif                          /* P11W */
07270 
07281 int
07282 edt_device_id(EdtDev *edt_p)
07283 {
07284     if (edt_p)
07285         return edt_p->devid;
07286     return -1;
07287 }
07288 
07303 int
07304 edt_check_1_vs_4(EdtDev *edt_p)
07305 {
07306     char name[129];
07307     int pci_channels = 4;
07308 
07309     edt_flash_get_fname(edt_p, name);
07310 
07311     if (isdigit(name[strlen(name)-1]))
07312     {
07313         if (strlen(name) >= 2 && isdigit(name[strlen(name)-2]))
07314         {
07315             pci_channels = atoi(name + strlen(name)-2);
07316         }
07317         else
07318         {
07319             pci_channels = atoi(name + strlen(name)-1);
07320         }
07321     }
07322 
07323     return pci_channels;
07324 }
07325 
07326 
07337 int
07338 edtdev_channels_from_type(EdtDev *edt_p)
07339 
07340 {
07341     if (edt_is_4channel(edt_p)) return 4;
07342     if (edt_is_1or4channel(edt_p)) return edt_check_1_vs_4(edt_p);
07343     if (edt_is_2channel(edt_p)) return 2;
07344     if (edt_is_3channel(edt_p)) return 3;
07345     if (edt_is_1553(edt_p)) return 34;
07346     if (edt_is_16channel(edt_p)) return 16;
07347     if (edt_is_32channel(edt_p)) return 32;
07348     return 1;
07349 
07350 }
07351 
07356 int
07357 edt_devtype_from_id(int id)
07358 {
07359     if (id == P11W_ID) return p11w;
07360     if (id == P16D_ID) return p16d;
07361     if (ID_IS_PCD(id)) return pcd;
07362     if (ID_IS_PDV(id)) return pdv;
07363     if (ID_IS_DUMMY(id)) return dummy;
07364     return unknown;
07365 }
07366 
07367 
07368 
07378 char *
07379 edt_idstring(int id, int promcode)
07380 {
07381     if (promcode == AMD_XC5VLX30T_A) {
07382         switch(id) {
07383             case PE4DVCL_ID:    return ("pcie4 dva c-link");
07384             case PE8DVCL_ID:    return ("pcie8 dva c-link");
07385             case PE8DVCLS_ID:   return ("pcie8 dva cls");
07386         }
07387     }
07388     return edt_idstr(id);
07389 }
07390 
07401 char *
07402 edt_idstr(int id)
07403 {
07404     switch(id)
07405     {
07406 
07407 /* ALERT: SEE EDT_IDSTRING FOR THESE GUYS which need promcode to distinguish between 'a' and non 'a' versions
07408 *    case PE4DVCL_ID:     return ("pcie4 dva c-link");
07409 *    case PE8DVCL_ID:     return ("pcie8 dva c-link");
07410 *    case PE8DVCLS_ID:    return ("pcie8 dva cls");
07411 */
07412     case PE1DVVL_ID:      return ("VisionLink F1");
07413     case PE4DVVL_ID:      return ("VisionLink F4");
07414     case PE4DVVLSIM_ID:   return ("VisionLink S4");
07415     case PE4DVVLFOX_ID:   return ("VisionLink FOX4");
07416 
07417     case P11W_ID:         return("pci 11w");
07418     case P16D_ID:         return("pci 16d");
07419     case PDV_ID:          return("pci dv");
07420     case PDVA_ID:         return("pci dva");
07421     case PDVA16_ID:       return("pci dva16");
07422     case PDVK_ID:         return("pci dvk");
07423     case PDVRGB_ID:       return("pci dv-rgb");
07424     case PDV44_ID:        return("pci dv44");
07425     case PDVCL_ID:        return("pci dv c-link");
07426     case PDVCL2_ID:       return("pci dv cls");
07427     case PE4DVCL_ID:      return("pcie4 dv c-link");
07428     case PE8DVCL_ID:      return("pcie8 dv c-link");
07429     case PE8DVCLS_ID:     return("pcie8 dv cls");
07430     case PDVAERO_ID:      return("pcd dv aero serial");
07431     case PCD20_ID:        return("pci cd-20");
07432     case PCD40_ID:        return("pci cd-40");
07433     case PCD60_ID:        return("pci cd-60");
07434     case PCDA_ID:         return("pci cda");
07435     case PCDCL_ID:        return("pci cd cl");
07436     case PGP20_ID:        return("pci gp-20");
07437     case PGP40_ID:        return("pci gp-40");
07438     case PGP60_ID:        return("pci gp-60");
07439 
07440     case PGP_THARAS_ID:   return("pci gp-tharas");
07441     case PGP_ECL_ID:      return("pci gp-ecl");
07442     case PCD_16_ID:       return("pci cd-16");
07443 
07444     case PCDA16_ID:       return("pci cda16");
07445     case PE4CDA_ID:       return("pcie4 cda");
07446     case PE4CDA16_ID:     return("pcie4 cda16");
07447 
07448     case PDVFCI_AIAG_ID:  return("pci-fci aiag");
07449     case PDVFCI_USPS_ID:  return("pci-fci usps");
07450     case PCDFCI_SIM_ID:   return("pci-fci sim");
07451     case PCDFCI_PCD_ID:   return("pci-fci pcd");
07452     case PCDFOX_ID:       return("pcd fox");
07453     case PDVFOX_ID:       return("pci dv fox");
07454     case PE4DVFOX_ID:     return("pcie4 dva fox");
07455     case PE8DVFOX_ID:     return("pcie8 dva fox");
07456     case P53B_ID:         return("pci 53b");
07457     case PDVFOI_ID:       return("pdv foi");
07458     case PSS4_ID:         return("pci ss-4");
07459     case PSS16_ID:        return("pci ss-16");
07460     case PGS4_ID:         return("pci gs-4");
07461     case PGS16_ID:        return("pci gs-16");
07462     case PE8LX1_ID:       return("pcie8 lx-1");
07463     case PE8LX16_LS_ID:   return("pcie8 lx-16 (slow)");
07464     case PE8LX16_ID:      return("pcie8 lx-16");
07465     case PE8LX32_ID:      return("pcie8 lx-32");
07466     case PE4AMC16_ID:     return("pcie4 AMC16");
07467     case PE8G3S5_ID:      return("pcie8 g3s5");
07468     case PE8G3KU_ID:      return("pcie8 g3ku");
07469     case WSU1_ID:         return("wsu 1");
07470     case SNAP1_ID:        return("snap 1");
07471     case DMY_ID:          return("dummy");
07472     case DMYK_ID:         return("dummy pci dvk/44/foi");
07473     case PC104ICB_ID:     return("pc104 icb");
07474     case PE4BL_RADIO_ID:  return("pcie4 lcr radio blade");
07475     case PE1BL_TIMING_ID: return("pcie1 lcr timing blade");
07476     case PE8BL_10GNIC_ID:  return("pcie8 lcr 2x10g nic blade");
07477     case LCRBOOT_ID:      return("lcr boot");
07478     case PE8G2V7_ID:      return("pcie8 g2v7");
07479     case UNKNOWNAB_ID:    return("unknown 00ab"); /* change when assigned */
07480     case UNKNOWNAC_ID:    return("unknown 00ac"); /* change when assigned */
07481     case UNKNOWNAD_ID:    return("unknown 00ad"); /* change when assigned */
07482     case UNKNOWNAE_ID:    return("unknown 00ae"); /* change when assigned */
07483     case UNKNOWNAF_ID:    return("unknown 00af"); /* change when assigned */
07484     default:              return("unknown");
07485     }
07486 }
07487 
07488 /*
07489  * Return the PCI FPGA boot-sector header string.
07490  * 
07491  * EDT PCI FPGA headers are embedded in the device's FPGA PROM and identify the specific FPGA
07492  * firmware running on the board. The specific format is hardware-dependent, but typically
07493  * consists of the name, build id, date, and time, with each field separated by whitespace.
07494  *
07495  * By convention, EDT PCI FPGA names are of the form name-XX.ext where XX is the rev number and
07496  * ext is the extension. The rev number will be present in the header string but is typically omitted
07497  * in the actual file name. Additionally, the extension is usually different -- in the header it will
07498  * likely be .ncd or .rpd, whereas the filename extension is virtually always .bit.  For example, the
07499  * PROM header name edt_firmware-02.rbt would most likely match a file named edt_firmware.bit in your
07500  * package (to find out whether a  given FPGA firmware file matches the one in the board's PROM,
07501  * use pciload verify.)
07502  *
07503  * @param edt_p pointer to edt device structure returned by #edt_open
07504  * @param name character string to store the device (must be of sufficient length to store the header
07505  * string; typically less than 80 characters but could be up to (and will be truncated to) 128 including
07506  * the trailing NULL.
07507  * @return
07508  */ 
07509 char *
07510 edt_get_flash_prom_header(EdtDev *edt_p, char *name)
07511 {
07512     int i;
07513     u_short stat;
07514     u_char jumpers, idbits, xidbits;
07515     int promcode;
07516     EdtPromData pdata;
07517     Edt_prominfo *ep;
07518 
07519     promcode = edt_flash_prom_detect(edt_p, &stat);
07520     ep = edt_get_prominfo(promcode);
07521     jumpers = stat & 0x3;
07522     idbits = (stat >>2) & 0x1f;
07523     xidbits = stat >> 8;
07524 
07525     ep = edt_get_prominfo(promcode);
07526     edt_read_prom_data(edt_p, promcode, ep->defaultseg, &pdata);
07527 
07528     if (promcode > edt_get_max_promcode())
07529         sprintf(name, "unknown [%02x %02x]", idbits, xidbits);
07530     else strncpy(name, pdata.id, 127);
07531 
07532     return name;
07533 }
07534 
07535 
07542 #if defined(VXWORKS) || defined(TEST_VXWORKS)
07543 /* writable command string for vxworks calling edt_system() */
07544 char edt_vxw_cmdstr[512];
07545 
07546 /*
07547 * The following two arrays are used to register a function name with a
07548 * function pointer for vxworks calling edt_system().  Only 32 unique
07549 * program names are supported; most programs use less than 5.
07550 *
07551 * STRATEGY:  Preference is simplicity, but works with most applications.
07552 */
07553 static char *program_func_name[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07554 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07555 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07556 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
07557 static void * edt_vx_system_func[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07558 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07559 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07560 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
07561 
07562 /*
07563 * VxWorks programs calling edt_system() must first register the progam name
07564 * and the program function.
07565 */
07566 int
07567 edt_vx_system_register_func(const char *funcstr, int (funcptr)(char *))
07568 {
07569     int i;
07570 
07571     for (i = 0; i < 32; i++)
07572     {
07573         if (program_func_name[i] == NULL)
07574             break;
07575     }
07576 
07577     if (i == 32)
07578         return(-1);
07579     else
07580     {
07581         program_func_name[i] =  edt_alloc(strlen(funcstr) + 1);
07582         strcpy(program_func_name[i], funcstr);
07583         edt_vx_system_func[i] = funcptr;
07584         return 0;
07585     }
07586 }
07587 #endif
07588 
07589 int
07590 edt_system(const char *cmdstr)
07591 {
07592 #if defined(_NT_)
07593 
07594     int ret;
07595     char *newstr = (char *) malloc(512) ;
07596     char *p = newstr ;
07597     int nowait = 0;
07598     char *arg[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07599         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07600         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07601         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07602     };
07603     int i ;
07604 
07605     if (cmdstr == NULL || *cmdstr == '\0')
07606         return(0) ;
07607 
07608     strncpy(newstr, cmdstr, 511) ;
07609     for (i = 0; (i < 32) && (p && *p); i++)
07610     {
07611         while (*p == ' ' || *p == '\t')
07612             *p++ = '\0' ;
07613 
07614         arg[i] = p ;
07615 
07616         while (*p != ' ' && *p != '\t' && *p != '\0')
07617             ++ p ;
07618     }
07619 
07620     if (*arg[i-1] == '&')
07621     {
07622         arg[i-1] = NULL;
07623         nowait = 1;
07624     }
07625 
07626     ret = (int)spawnv((nowait) ? _P_NOWAIT : _P_WAIT, arg[0], arg);
07627 
07628     free(newstr);
07629     return ret;
07630 #elif defined(VXWORKS) || defined(TEST_VXWORKS)
07631     /*
07632     * VxWorks programs calling edt_system() must first register the progam name
07633     * and the program function.  Here the string argument to edt_system() is
07634     * parsed into the command name and options.  The command name is looked up
07635     * and matched with a function pointer, then the function is called with
07636     * the option string.
07637     */
07638     {
07639         int i;
07640         char *cmd;
07641         char *opts;
07642         char *tmp;
07643         int (*fnp)(char *);
07644 
07645         strncpy(edt_vxw_cmdstr, cmdstr, 511);
07646         cmd = edt_vxw_cmdstr;
07647         opts = strchr(edt_vxw_cmdstr, ' ');
07648 
07649         if (opts)
07650             *opts++ = '\0';
07651 
07652         tmp = strrchr(edt_vxw_cmdstr, '/');
07653         if (tmp)
07654             cmd = tmp + 1;
07655 
07656 
07657         edt_msg(EDTDEBUG, "VXWORKS_test: edt_system(%s, %s)\n", cmd, opts);
07658 #if defined(TEST_VXWORKS)
07659         printf("VXWORKS_test: edt_system(%s, %s)\n", cmd, opts);
07660 #endif
07661 
07662         for (i = 0; i < 32; i++)
07663         {
07664             if (program_func_name[i] == NULL)
07665                 return -1;
07666             else if (strncmp(program_func_name[i], cmd, 511) == 0)
07667             {
07668                 fnp = (int (*)(char*)) edt_vx_system_func[i];
07669                 edt_msg(EDTDEBUG, "VXWORKS_test: found name %s func %p\n", cmd, fnp);
07670                 return fnp(opts);
07671             }
07672         }
07673 
07674         if (i == 32) /* Not found */
07675         {
07676             edt_msg(EDTDEBUG, "VXWORKS_test: name not found %s, must be registered with edt_vx_system_register_func()\n", cmd);
07677             return -1;
07678         }
07679     }
07680     return(0);
07681 }
07682 #else
07683 
07684     int                ret ;
07685 
07686     ret      = system(cmdstr) ;
07687 
07688 #if defined(__sun) || defined(__linux__) || defined(__APPLE__)
07689     if (ret == -1 || WIFEXITED(ret) == 0)
07690         return -1 ;
07691     else
07692         return WEXITSTATUS(ret)      ;
07693 #else
07694     return ret ;
07695 #endif
07696 #endif
07697 }
07698 
07699 #define MEZZ_PATH_FIELD_CHAR '|'
07700 
07701 char *
07702 edt_get_last_bitpath(EdtDev *edt_p)
07703 
07704 {
07705     FILE *f;
07706     static char cache_name[MAXPATH];
07707 
07708 
07709     sprintf(cache_name, ".interface_bitfile.%d", edt_p->unit_no);
07710 
07711     if ((f = fopen(cache_name, "r")))
07712     {
07713 
07714         volatile char *throwaway = fgets(cache_name, MAXPATH, f);
07715 
07716         if (strlen(cache_name))
07717         {
07718 
07719             if (cache_name[strlen(cache_name)-1] == '\n')
07720                 cache_name[strlen(cache_name)-1] = 0;
07721         }
07722 
07723         fclose(f);
07724 
07725         return cache_name;
07726     }
07727 
07728     return NULL;
07729 }
07730 
07731 
07732 void
07733 edt_set_last_bitpath(EdtDev *edt_p, const char *fullpath)
07734 
07735 {
07736     FILE *f;
07737     char cache_name[MAXPATH];
07738 
07739     sprintf(cache_name, ".interface_bitfile.%d", edt_p->unit_no);
07740 
07741     if ((f = fopen(cache_name, "w")))
07742     {
07743 
07744         fputs(fullpath, f);
07745 
07746         fclose(f);
07747 
07748     }
07749 }
07750 
07751 
07765 int
07766 edt_set_mezz_chan_bitpath(EdtDev *edt_p, const char *bitpath, int channel)
07767 {
07768     edt_bitpath pathbuf, chan0, chan1;
07769     const char *s1;
07770     int sp;
07771     int rc;
07772 
07773     /* scan back for / in path - we may not have room for full path */
07774 
07775     if (strlen(bitpath))
07776     {
07777         sp = (int) strlen(bitpath) - 1;
07778 
07779         while (sp >= 0 && bitpath[sp] != '/' && bitpath[sp] != '\\')
07780             sp --;
07781 
07782         if (sp >= 0)
07783             sp++;
07784         else
07785             sp = 0;
07786     }
07787     else
07788         sp = 0;
07789 
07790     s1 = bitpath + sp;
07791 
07792     edt_get_mezz_chan_bitpath(edt_p,chan0, sizeof(chan0),0);
07793     edt_get_mezz_chan_bitpath(edt_p,chan1, sizeof(chan1),1);
07794 
07795     if (channel == 0)
07796         sprintf(pathbuf,"%s%c%s",s1,MEZZ_PATH_FIELD_CHAR,chan1);
07797     else
07798         sprintf(pathbuf,"%s%c%s",chan0, MEZZ_PATH_FIELD_CHAR, s1);
07799 
07800     rc = edt_ioctl(edt_p, EDTS_MEZZ_BITPATH, pathbuf);
07801 
07802     edt_get_mezz_chan_bitpath(edt_p, edt_p->bfd.mezz_name0,
07803         sizeof(edt_p->bfd.mezz_name0),0);
07804     edt_get_mezz_chan_bitpath(edt_p, edt_p->bfd.mezz_name1,
07805         sizeof(edt_p->bfd.mezz_name1),1);
07806 
07807     return rc;
07808 }
07809 
07810 
07825 int
07826 edt_get_mezz_chan_bitpath(EdtDev *edt_p, char *bitpath, int size, int channel)
07827 {
07828     int ret = 0 ;
07829     edt_bitpath pathbuf ;
07830     char *s2, *s3;
07831     int sp;
07832     /* split into channels */
07833 
07834     ret = edt_ioctl(edt_p, EDTG_MEZZ_BITPATH, pathbuf);
07835 
07836     s2 = pathbuf;
07837     sp = 0;
07838     while (sp < (int)strlen(pathbuf) && pathbuf[sp] != MEZZ_PATH_FIELD_CHAR)
07839         sp++;
07840 
07841     s3 = s2 + sp;
07842     if (s3[0] == MEZZ_PATH_FIELD_CHAR)
07843     {
07844         s3[0] = 0;
07845         s3++;
07846     }
07847 
07848     if (channel == 0)
07849         strncpy(bitpath, s2, size - 1) ;
07850     else
07851         strncpy(bitpath, s3, size - 1) ;
07852 
07853     return ret ;
07854 }
07855 
07867 int
07868 edt_set_mezz_bitpath(EdtDev *edt_p, const char *bitpath)
07869 {
07870     edt_bitpath pathbuf;
07871     int rc;
07872     int i = (int) strlen(bitpath)-1;
07873 
07874     while (i>= 0 && bitpath[i] != '\\' && bitpath[i] != '/')
07875         i--;
07876 
07877     if (i >= 0)
07878         i++;
07879     else
07880         i = 0;
07881 
07882     strncpy(pathbuf, bitpath+i, sizeof(edt_bitpath) - 1) ;
07883     rc =  edt_ioctl(edt_p, EDTS_MEZZ_BITPATH, pathbuf);
07884 
07885     return rc;
07886 }
07887 
07888 
07902 int
07903 edt_get_mezz_bitpath(EdtDev *edt_p, char *bitpath, int size)
07904 {
07905     int ret = 0 ;
07906     edt_bitpath pathbuf ;
07907 
07908     ret = edt_ioctl(edt_p, EDTG_MEZZ_BITPATH, pathbuf);
07909     strncpy(bitpath, pathbuf, size - 1) ;
07910     return ret ;
07911 }
07912 
07913 
07925 int
07926 edt_set_bitpath(EdtDev *edt_p, const char *bitpath)
07927 {
07928     edt_bitpath pathbuf ;
07929     int rc;
07930 
07931     strncpy(pathbuf, bitpath, sizeof(edt_bitpath) - 1) ;
07932     rc =  edt_ioctl(edt_p, EDTS_BITPATH, pathbuf);
07933 
07934     edt_get_bitname(edt_p, edt_p->bfd.bitfile_name,
07935         sizeof(edt_p->bfd.bitfile_name));
07936 
07937     edt_set_last_bitpath(edt_p, bitpath);
07938 
07939     return rc;
07940 }
07941 
07942 
07956 int
07957 edt_get_bitpath(EdtDev *edt_p, char *bitpath, int size)
07958 {
07959     int ret = 0 ;
07960     edt_bitpath pathbuf ;
07961     pathbuf[0] = '\0';
07962     ret = edt_ioctl(edt_p, EDTG_BITPATH, pathbuf);
07963 
07964     strncpy(bitpath, pathbuf, size - 1) ;
07965     return ret ;
07966 }
07967 
07981 int
07982 edt_get_bitname(EdtDev *edt_p, char *bitpath, int size)
07983 {
07984     int ret = 0 ;
07985     char *name;
07986     edt_bitpath pathbuf ;
07987 
07988     pathbuf[0] = '\0';
07989     ret = edt_ioctl(edt_p, EDTG_BITPATH, pathbuf);
07990 
07991     /*  Remove the leading path from the bitfile name */
07992     if ((name = strrchr(pathbuf, '/')) || (name = strrchr(pathbuf, '\\')))
07993         ++ name;
07994     else
07995         name = pathbuf;
07996 
07997     strcpy(bitpath, name) ;
07998 
07999     return ret ;
08000 }
08001 
08013 int
08014 edt_get_driver_version(EdtDev *edt_p, char *version, int size)
08015 {
08016     int ret = 0 ;
08017     edt_version_string vbuf ;
08018 
08019     ret = edt_ioctl(edt_p, EDTG_VERSION, vbuf);
08020 
08021     strncpy(version, vbuf, size - 1) ;
08022     return ret ;
08023 }
08024 
08037 int
08038 edt_get_driver_buildid(EdtDev *edt_p, char *build, int size)
08039 {
08040     int ret = 0 ;
08041     edt_version_string vbuf ;
08042 
08043     ret = edt_ioctl(edt_p, EDTG_BUILDID, vbuf);
08044 
08045     strncpy(build, vbuf, size - 1) ;
08046     return ret ;
08047 }
08048 
08049 static char * edt_library_version = EDT_LIBRARY_VERSION;
08050 static char * edt_library_buildid = FULLBUILD;
08051 
08061 int
08062 edt_get_library_version(EdtDev *edt_p, char *version, int size)
08063 {
08064     strncpy(version, edt_library_version, size - 1) ;
08065     return 0 ;
08066 }
08067 
08068 u_int
08069 edt_get_version_number()
08070 
08071 {
08072     char id_n[64];
08073 
08074     u_int vi = 0;
08075     int starti;
08076     int i;
08077 
08078     strncpy(id_n, edt_library_version, 63);
08079 
08080     starti = 0;
08081     for (i=0;; i++)
08082     {
08083         if (!isdigit(id_n[i]))
08084         {
08085 
08086             vi = (vi << 8) | atoi(id_n+starti);
08087 
08088             starti = i+1;
08089 
08090             if (id_n[i] != '.')
08091                 break;
08092         }
08093 
08094 
08095     }
08096 
08097     return vi;
08098 
08099 
08100 }
08101 
08111 int
08112 edt_get_library_buildid(EdtDev *edt_p, char *build, int size)
08113 {
08114     strncpy(build, edt_library_buildid, size - 1) ;
08115     return 0 ;
08116 }
08117 
08118 
08122 int
08123 edt_check_version(EdtDev *edt_p)
08124 
08125 {
08126     edt_version_string check;
08127 
08128     edt_get_driver_version(edt_p, check, sizeof(check));
08129 
08130     return (!strcmp(check,edt_library_version));
08131 
08132 }
08133 
08137 static u_int
08138 epr_cfg(EdtDev *edt_p, int addr)
08139 {
08140     int ret ;
08141     edt_buf buf ;
08142     buf.desc = addr ;
08143     if ((addr<0) || (addr>0x3c)) {
08144         edt_msg(EDTWARN, "epr_cfg: addr out of range\n");
08145         return(0);
08146     }
08147     ret = edt_ioctl(edt_p,EDTG_CONFIG,&buf) ;
08148     if (ret < 0)
08149     {
08150         edt_perror("EDTG_CONFIG") ;
08151     }
08152     return(u_int) (buf.value) ;
08153 }
08154 
08155 static void
08156 epw_cfg(EdtDev *edt_p, int addr, int value)
08157 {
08158     int ret ;
08159     edt_buf buf ;
08160     buf.desc = addr ;
08161     if ((addr<0) || (addr>0x3c)) {
08162         edt_msg(EDTWARN, "epw_cfg: addr out of range\n");
08163         return;
08164     }
08165     buf.value = value ;
08166     ret = edt_ioctl(edt_p,EDTS_CONFIG,&buf) ;
08167     if (ret < 0)
08168     {
08169         edt_perror("EDTS_CONFIG") ;
08170     }
08171 }
08172 
08178 int
08179 edt_pci_reboot(EdtDev *edt_p)
08180 {
08181     int  addr, data;
08182     int  buf[0x40];
08183     int  rst, copy, new_one;
08184     int  ret = 0;
08185     FILE *fd2;
08186     char *tmpfname = "TMPfPciReboot.cfg";
08187 
08188     if ((fd2 = fopen(tmpfname, "wb")) == NULL)      {
08189         edt_msg(EDTFATAL,"edt_pci_reboot: Couldn't write to temp file %s\n", tmpfname);
08190         return -1;
08191     }
08192     for (addr=0; addr<=0x3c; addr+=4) {
08193         data  = epr_cfg(edt_p, addr);
08194         buf[addr] = data;
08195         putc(data, fd2);
08196         putc(data>>8, fd2);
08197         putc(data>>16, fd2);
08198         putc(data>>24, fd2);
08199         /* printf("%02x:  %08x\n", addr, data); */
08200     }
08201     fclose(fd2);
08202     edt_msg(EDTDEBUG, "Wrote config space state out to %s\n", tmpfname);
08203 
08204     edt_reg_write(edt_p, 0x01000085, 0x40) ;
08205     edt_msleep(2000) ;
08206 
08207     edt_msg(EDTDEBUG, "  copy     reset     new\n");
08208     for (addr=0; addr<=0x3c; addr+=4) {
08209         rst  = epr_cfg(edt_p, addr);
08210         copy  =  buf[addr];
08211         epw_cfg(edt_p, addr, copy) ;
08212         new_one  = epr_cfg(edt_p, addr);
08213 
08214         edt_msg(EDTDEBUG, "%02x:  %08x  %08x  %08x       ", addr, copy, rst, new_one);
08215         if      (copy != new_one)       edt_msg(EDTDEBUG, "ERROR\n");
08216         else if (rst != new_one)    edt_msg(EDTDEBUG, "changed\n");
08217         else                    edt_msg(EDTDEBUG, "\n");
08218 
08219         /* specifically check line cache reg to make sure it was reset by OS after cleared */
08220         if (addr == 0x0c)
08221         {
08222             if ((rst & 0xff) == (new_one & 0xff))
08223                 ret = -1;
08224         }
08225 
08226     }
08227     return ret;
08228 }
08229 
08233 int
08234 edt_set_merge(EdtDev * edt_p, u_int size, int span, u_int offset, u_int count)
08235 {
08236     edt_merge_args tmp;
08237     int     ret;
08238 
08239     tmp.line_size = size ;
08240     tmp.line_span = span;
08241     tmp.line_offset = offset;
08242     tmp.line_count = count;
08243     ret = edt_ioctl(edt_p, EDTS_MERGEPARMS, &tmp);
08244     return (ret);
08245 }
08246 
08247 /* flip the bits inside a byte */
08248 u_char
08249 edt_flipbits(u_char val)
08250 {
08251     int     i;
08252     u_char  ret = 0;
08253 
08254     for (i = 0; i < 8; i++)
08255     {
08256         if (val & (1 << i))
08257             ret |= 0x80 >> i;
08258     }
08259     return (ret);
08260 }
08261 
08262 
08263 /*
08264 *
08265 * edt_set_kernel_buffers
08266 *
08267 * Turn on or off the use of intermediate kernel buffers for DMA
08268 * Use for instance in Linux > 4 Gb, where DMA fails for high memory
08269 *
08270 */
08271 
08272 int
08273 edt_set_kernel_buffers(EdtDev * edt_p, int onoff)
08274 
08275 {
08276     uint_t val = (uint_t) onoff;
08277 
08278     edt_ioctl(edt_p, EDTS_DRV_BUFFER, &val);
08279 
08280     return val;
08281 }
08282 /*
08283 *
08284 * edt_get_kernel_buffers
08285 *
08286 * Returns the current kbufs state
08287 *
08288 */
08289 
08290 int
08291 edt_get_kernel_buffers(EdtDev * edt_p)
08292 
08293 {
08294     uint_t val = (uint_t) -1;
08295 
08296     if (edt_p->devid == DMY_ID)
08297         val = 0 ;
08298     else
08299         edt_ioctl(edt_p, EDTS_DRV_BUFFER, &val);
08300 
08301     return val;
08302 }
08303 
08304 int
08305 edt_set_mmap_buffers(EdtDev *edt_p, int state)
08306 
08307 {
08308 
08309     uint_t val = edt_get_kernel_buffers(edt_p) & ~EDT_MMAP_KBUFS;
08310 
08311     val |= (state)?EDT_MMAP_KBUFS:0;
08312 
08313     return edt_ioctl(edt_p, EDTS_DRV_BUFFER, &val);
08314 
08315 
08316 }
08317 
08318 int
08319 edt_get_mmap_buffers(EdtDev *edt_p)
08320 
08321 {
08322 
08323     int rc = (edt_get_kernel_buffers(edt_p) & EDT_MMAP_KBUFS) != 0;
08324 
08325     return rc;
08326 }
08327 
08328 int
08329 edt_get_persistent_buffers(EdtDev * edt_p)
08330 
08331 {
08332     uint_t val = (uint_t) -1;
08333 
08334     edt_ioctl(edt_p, EDTS_DRV_BUFFER, &val);
08335 
08336     printf("val = %d\n", val);
08337 
08338     return (val & EDT_PERSISTENT_KBUFS) != 0;
08339 }
08340 
08341 int
08342 edt_set_persistent_buffers(EdtDev * edt_p, int state)
08343 
08344 {
08345 
08346     uint_t val = edt_get_kernel_buffers(edt_p) & ~EDT_PERSISTENT_KBUFS;
08347 
08348     val |= (state)?EDT_PERSISTENT_KBUFS:0;
08349 
08350     return edt_ioctl(edt_p, EDTS_DRV_BUFFER, &val);
08351 
08352 }
08353 
08399 u_int
08400 edt_get_dma_info(EdtDev * edt_p, edt_dma_info *dmainfo)
08401 {
08402     edt_dma_info tmpinfo ;
08403 
08404     edt_ioctl(edt_p, EDTG_DMA_INFO, &tmpinfo);
08405 
08406     if (dmainfo) *dmainfo = tmpinfo ;
08407 
08408     return (tmpinfo.used_dma | tmpinfo.alloc_dma | tmpinfo.active_dma) ;
08409 }
08410 
08424 int
08425 edt_find_xpn(char *part_number, char *fpga)
08426 {
08427     return edt_get_xref_info("./edt_parts.xpn", (const char *)part_number, fpga, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
08428 }
08429 
08462 int
08463 edt_get_xref_info(const char *path, const char *pn, char *fpga, char *sn, char *mtype, char *moffs, char *mcount, char *desc, char *rsvd1, char *rsvd2)
08464 {
08465     int ret = 0;
08466     FILE *xfp;
08467     char str[EDT_STRBUF_SIZE];
08468     char xf_pn[EDT_STRBUF_SIZE], xf_fpga[EDT_STRBUF_SIZE];
08469 
08470     if ((xfp = fopen(path, "r")) == NULL)
08471     {
08472         char errmsg[EDT_STRBUF_SIZE];
08473         sprintf(errmsg, "couldn't open '%s'\n", path);
08474         edt_msg(EDTWARN, errmsg);
08475         return 0;
08476     }
08477 
08478     while (fgets(str, EDT_STRBUF_SIZE, xfp) != NULL)
08479     {
08480 
08481         if ((strlen(str) > 10) && (*str >= '0') && (*str <= '9')) /* valid lines begin with a part number */
08482         {
08483             int n;
08484 
08485             /* check for part number match, make sure there's at least one more field (fpga) */
08486             if ((n = sscanf(str, "%s %s", xf_pn, xf_fpga)) == 2)
08487             {
08488                 /* first check for 10-digit part number match; if found use this line and return */
08489                 if ((strlen(xf_pn) == 10) && (strcasecmp(xf_pn, pn) == 0))
08490                 {
08491                     ret = get_xref_info_params(str, fpga, sn, mtype, moffs, mcount, desc, rsvd1, rsvd2);
08492 
08493                     fclose(xfp);
08494                     return ret;
08495                 }
08496 
08497                 /* no 10-digit so far, check for 8-digit but don't return yet, */
08498                 /* in case there's a 10-digit one still to be found */
08499                 else if ((strlen(xf_pn) == 8) && (strncasecmp(xf_pn, pn, 8) == 0))
08500                 {
08501                     ret = get_xref_info_params(str, fpga, sn, mtype, moffs, mcount, desc, rsvd1, rsvd2);
08502                 }
08503             }
08504         }
08505     }
08506 
08507     fclose(xfp);
08508 
08509     return ret;
08510 }
08511 
08515 static int
08516 get_xref_info_params(char *str, char *fpga, char *sn, char *mtype, char *moffs, char *mcount, char *desc, char *rsvd1, char *rsvd2)
08517 {
08518     int n, ret = 0;
08519     char xf_partnum[128], xf_fpga[128], xf_sn[128], xf_mtype[128], xf_moffs[128], xf_mcount[128], xf_desc[128], xf_rsvd1[128], xf_rsvd2[128];
08520 
08521     if (fpga) fpga[0] = '\0';
08522     if (sn) sn[0] = '\0';
08523     if (mtype) mtype[0] = '\0';
08524     if (moffs) moffs[0] = '\0';
08525     if (mcount) mcount[0] = '\0';
08526     if (desc) desc[0] = '\0';
08527     if (rsvd1) rsvd1[0] = '\0';
08528     if (rsvd2) rsvd2[0] = '\0';
08529 
08530     n = sscanf(str, "%s %s %s %s %s %s \"%64[^\"]s\" %s", xf_partnum, xf_fpga, xf_sn, xf_mtype, xf_moffs, xf_mcount, xf_desc, xf_rsvd1, xf_rsvd2);
08531 
08532     /* check if the xf_fpga arg looks like an fpga */
08533     if ((n > 1) && fpga && (strlen(xf_fpga) > 1) && (strlen(xf_fpga) <= 64))
08534     {
08535         strcpy(fpga, xf_fpga);
08536         ++ret;
08537     }
08538 
08539     /* check if the arg looks like a serial number (old format didn't have this) */
08540     if ((n > 2) && sn && (strlen(xf_sn) > 5) && (strlen(xf_sn) < 25))
08541     {
08542         int i;
08543 
08544         /* walk backward from the end to make sure there are at least 3 trailing digits */
08545         strcpy(sn, xf_sn);
08546         ++ret;
08547         for (i=strlen(xf_sn)-1; i > strlen(xf_sn) - 4; i--)
08548         {
08549             if (!isdigit(xf_sn[i]))
08550             {
08551                 sn[0] = '\0';
08552                 --ret;
08553                 break;
08554             }
08555         }
08556     }
08557 
08558     /* check if the arg looks like a mac type -- s/b 1-3 digit numeric (old format didn't have this) */
08559     if ((n > 3) && mtype && (strlen(xf_mtype) > 0) && (strlen(xf_mtype) <= 3) && isdigit_str(xf_mtype))
08560     {
08561         strcpy(mtype, xf_mtype);
08562         ++ret;
08563     }
08564 
08565     /* check if the arg looks like a mac offset -- s/b 1-3 digit numeric (old format didn't have this) */
08566     if ((n > 4) && moffs && (strlen(xf_moffs) > 0) && (strlen(xf_moffs) <= 3) && isdigit_str(xf_moffs))
08567     {
08568         strcpy(moffs, xf_moffs);
08569         ++ret;
08570     }
08571 
08572     /* check if the arg looks like a mac count -- s/b 1-3 digit numeric (old format didn't have this) */
08573     if ((n > 5) && mcount && (strlen(xf_mcount) > 0) && (strlen(xf_mcount) <= 3) && isdigit_str(xf_mcount))
08574     {
08575         strcpy(mcount, xf_mcount);
08576         ++ret;
08577     }
08578 
08579     /* check if the arg looks like a description -- s/b 3-128 chars (old format didn't have this) */
08580     if ((n > 6) && desc && (strlen(xf_desc) > 3) && (strlen(xf_desc) <= 128))
08581     {
08582         strcpy(desc, xf_desc);
08583         ++ret;
08584     }
08585 
08586     /* N > 7: future */
08587     if (n > 7)
08588         strcpy(rsvd1, xf_rsvd1);
08589 
08590     if (n > 8)
08591         strcpy(rsvd2, xf_rsvd2);
08592 
08593     return ret;
08594 }
08595 
08596 static int
08597 isdigit_str(char *s)
08598 {
08599     u_int i;
08600 
08601     for (i=0; i<strlen(s); i++)
08602         if ((s[i]) < '0' || s[i] > '9')
08603             return 0;
08604     return 1;
08605 }
08606 
08607 int
08608 edt_user_dma_wakeup(EdtDev *edt_p)
08609 {
08610     u_int i = 1;
08611 
08612 #ifdef _NT_
08613     HANDLE event;
08614     int rc;
08615 
08616     if (!edt_p->event_funcs[EDT_EVENT_BUF].wait_event)
08617     {
08618         edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
08619     }
08620 
08621     event = edt_p->event_funcs[EDT_EVENT_BUF].wait_event;
08622 
08623     rc = SetEvent(event);
08624     rc = ResetEvent(event);
08625 
08626     edt_p->last_wait_ret = EDT_WAIT_USER_WAKEUP;
08627     return !rc;
08628 
08629 #else
08630 
08631     return edt_ioctl(edt_p,EDTS_USER_DMA_WAKEUP,&i);
08632 
08633 #endif
08634 
08635 }
08636 
08637 int
08638 edt_had_user_dma_wakeup(EdtDev *edt_p)
08639 {
08640     u_int i = 0;
08641 #ifdef _NT_
08642     return edt_p->last_wait_ret == EDT_WAIT_USER_WAKEUP;
08643 #endif
08644     edt_ioctl(edt_p,EDTG_USER_DMA_WAKEUP,&i);
08645 
08646     return i;
08647 }
08648 
08649 int
08650 edt_get_wait_status(EdtDev *edt_p)
08651 
08652 {
08653     u_int i = 0;
08654 
08655 #ifdef _NT_
08656     return edt_p->last_wait_ret;
08657 #else
08658     edt_ioctl(edt_p,EDTG_WAIT_STATUS,&i);
08659 #endif
08660     return i;
08661 
08662 }
08663 
08664 int
08665 edt_clear_wait_status(EdtDev *edt_p)
08666 
08667 {
08668     u_int i = 0;
08669 
08670 #ifdef _NT_
08671     edt_p->last_wait_ret = 0;
08672 #else
08673     edt_ioctl(edt_p,EDTS_WAIT_STATUS,&i);
08674 #endif
08675     return i;
08676 
08677 }
08678 
08679 int
08680 edt_set_timeout_ok(EdtDev *edt_p, int val)
08681 
08682 {
08683     return edt_ioctl(edt_p,EDTS_TIMEOUT_OK,&val);
08684 }
08685 
08686 int
08687 edt_get_timeout_ok(EdtDev *edt_p)
08688 
08689 {
08690     u_int i = 0;
08691 
08692     edt_ioctl(edt_p,EDTG_TIMEOUT_OK,&i);
08693 
08694     return i;
08695 }
08696 
08697 #if 0
08698 
08699 DIR *opendir(char *dirName)
08700 {
08701     printf("opendir") ;
08702 }
08703 
08704 STATUS closedir(DIR *pDir)
08705 {
08706     printf("closedir") ;
08707 }
08708 struct dirent *readdir(DIR *pDir)
08709 {
08710     printf("readdir") ;
08711 }
08712 
08713 #endif
08714 
08715 u_int
08716 edt_set_mezz_id(EdtDev *edt_p)
08717 
08718 {
08719     int ret ;
08720     edt_buf mezz_args ;
08721 
08722     int chan;
08723 
08724 #ifdef WIN32
08725     mezz_args.value = (uint64_t) (&edt_p->mezz);
08726 #else
08727     mezz_args.value = (uint64_t) ((unsigned long) &edt_p->mezz);
08728 #endif
08729 
08730     for (chan = 0;chan<edt_p->DMA_channels;chan++)
08731     {
08732 
08733         EdtDev *test_edt;
08734 
08735         if (chan != edt_p->channel_no)
08736         {
08737             test_edt = edt_open_channel(EDT_INTERFACE, edt_p->unit_no, chan);
08738 
08739             if (test_edt)
08740             {
08741                 ret = edt_ioctl(test_edt, EDTS_MEZZ_ID, &mezz_args);
08742 
08743                 edt_close(test_edt);
08744             }
08745         }
08746     }
08747 
08748     ret = edt_ioctl(edt_p, EDTS_MEZZ_ID, &mezz_args);
08749 
08750     return ret;
08751 }
08752 
08753 u_int
08754 edt_get_mezz_id(EdtDev *edt_p)
08755 
08756 {
08757     int ret ;
08758     edt_buf mezz_args ;
08759 #ifdef WIN32
08760     mezz_args.value = (uint64_t) (&edt_p->mezz);
08761 #else
08762     mezz_args.value = (uint64_t) ((unsigned long) &edt_p->mezz);
08763 #endif
08764 
08765     ret = edt_ioctl(edt_p, EDTG_MEZZ_ID, &mezz_args);
08766 
08767     return ret;
08768 }
08769 
08770 /*
08771 * This function returns the normal or extended board id information from a mezannine board.
08772 */
08773 
08774 /*
08775 * The lower 4 bits of the MEZZANIN_BD_ID register always read back the 4 bits of board ID
08776 * from the mezzanine board. When all but one of the board ids where used EDT introduced
08777 * a extended board ID. The last 4 bit board ID (0x2) is used on all subsequent mezzanine
08778 * boards to indicate extended board id has been implemented.
08779 * The extended board ID is implemented in a XC9572XL CPLD using a serial read scheme similar
08780 * but not identical to I2C to read one or more 32 bit registers used for mezzanine id and revision.
08781 * The first word is 12 bits - number of 32 bit words (usually 1)
08782 *                   12 bits - extended board id
08783 *                    8 bits - version number
08784 * use of subsequent words is undefined
08785 *
08786 * The upper 4 bits of the MEZZANINE_BD_ID register controls the extended board id serial pins.
08787 * They are defined as follows:
08788 * bit 4 - Configuration file support for extended board id.
08789 *         This bit is set to a 1 by any User FPGA configuration file that implements
08790 *         the extend board ID functions described here. Previous configuration files
08791 *         for mezzanines without extend board id will always return 0 in bit 4 (actually
08792 *         bit4 to bit 7 as well)
08793 * bit 5 - Board ID serial data.
08794 *         When the FPGA is driving the bi-directional data line (bit 7 is low),
08795 *         then bit 5 is set to the desired state of the data signal. When the FPGA
08796 *         is tristate (bit 7 high) then bit reflects the state of the data signal.
08797 *         The data signal is pulled up on the mezzanines with a 10k resistor. If
08798 *         both the FPGA nad the CPLD are driving the data bus this bit will reflect
08799 *         the value desired by the FPGA not necessarily the actual state of the bus.
08800 * bit 6 - Board ID clock.
08801 *         The serial clock is always driven by the FPGA. When this bit is high the clock is
08802 *         high. When low the clock is low.
08803 * bit 7 - FPGA Serial Data Tristate.
08804 *         See bit 5 description.
08805 *
08806 * The protocol to read the CPLD register is as follows:
08807 * 1) Verify CPLD data is tristate by sending CLK_CPLD clocks.
08808 *    Even if the CPLD is left in the middle of a read this number
08809 *    of clocks should complete any possible read and tristate the data
08810 *    signal.
08811 * 2) Reset the CPLD. With the data enabled and low set the clock high,
08812 *    then set the data high and low to set a reset state. Toggle the
08813 *    clock at least 2 times (we use 5 here) to complete the reset.
08814 * 3) Read the data. With the data high set the clock hi, then set the data
08815 *    low. This sets the start state. Tristate the FPGA data and toggle the clock
08816 *    while reading the serial data from the CPLD on bit 5.
08817 * 4) After the data is read set the clock low, enable the FPGA data with the
08818 *    data low. Set the clock high and then the data high. This will set stop
08819 *    and reset the CPLD.
08820 */
08821 
08822 
08823 #define CLK_CPLD 500
08824 /* register masks */
08825 #define EDT_EXTBDID_IMPL        0x10
08826 #define EDT_EXTBDID_DATA        0x20
08827 #define EDT_EXTBDID_CLK         0x40
08828 #define EDT_EXTBDID_TS          0x80
08829 
08830 /*
08831 * read a 32 bit word from the cpld.
08832 * the start state has already been set
08833 */
08834 static u_int
08835 edt_read_extbdid_val(EdtDev *edt_p)
08836 
08837 {
08838     u_int ext_info = 0;
08839     int idcnt;          /* counter for reading bits from cpld */
08840     int bdidreg;
08841 
08842     for(idcnt = 31; idcnt >= 0; --idcnt)
08843     {
08844         /* toggle clock */
08845         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK);
08846         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS);
08847         /*
08848         edt_msleep(1);
08849         */
08850         bdidreg = edt_intfc_read(edt_p, MEZZANINE_BD_ID);
08851 
08852         if ((bdidreg & EDT_EXTBDID_DATA) != 0)
08853             ext_info |= 1 << idcnt;
08854     }
08855 
08856     return ext_info;
08857 
08858     /* clock is low, data is tristate at FPGA */
08859 
08860 }
08861 
08862 void edt_extbdid_stop(EdtDev *edt_p)
08863 {
08864     int init;
08865 
08866     /* one more clock to tristate CPLD data */
08867     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK);
08868     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS);
08869 
08870     /* set stop condition */
08871     edt_intfc_write(edt_p, MEZZANINE_BD_ID, 0); /* FPGA enabled and low, clock stays low */
08872     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK); /*clock hi */
08873     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK | EDT_EXTBDID_DATA); /* data hi sets stop */
08874     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /* clock low */
08875     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* tristate data while high */
08876 
08877     /* a few extra clocks to complete reset */
08878 
08879     for(init = 2; init > 0; --init)
08880     {
08881         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK);
08882         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS);
08883     }
08884 
08885     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK | EDT_EXTBDID_DATA);
08886     /* CPLD should be idle, clock high and data tristate (pulled up high) just like we should start */
08887 
08888 }
08889 
08890 /*
08891 * reset the CPLD from a completely unknown state
08892 * and set start state to begin read
08893 */
08894 void edt_extbdid_reset(EdtDev *edt_p)
08895 {
08896     int init;
08897     int bdidreg;
08898     /* clock cpld to make sure CPLD is tristate */
08899     /* force a start and then assume a start to get early rev cplds
08900     * to definitly be tristate. Requires pciss16test with 24 ma drive
08901     * on the data (to overpower a CPLD sstuck in tristate)
08902     */
08903 
08904     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* make data hi before enable*/
08905     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /*  enable FPGS on data bus */
08906     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK | EDT_EXTBDID_DATA); /* set clock hi */
08907     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK ); /* data low while clock high sets start */
08908     edt_intfc_write(edt_p, MEZZANINE_BD_ID, 0); /* clock low */
08909     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /*  data hi in prep for ts */
08910     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* ts data */
08911 
08912     for(init = CLK_CPLD; init > 0; --init)
08913     {
08914         /* toggle clock - disregard data */
08915         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK);
08916         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS);
08917     }
08918 
08919     bdidreg = edt_intfc_read(edt_p, MEZZANINE_BD_ID);
08920 
08921     if ((bdidreg & EDT_EXTBDID_DATA) == 0)
08922         printf("After %d loops BDID databus is still low\n", init);
08923 
08924     /* set both start and stop condition to reset */
08925     edt_intfc_write(edt_p, MEZZANINE_BD_ID, 0); /* FPGA enabled and low, clock stays low */
08926     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK); /*clock hi */
08927     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK | EDT_EXTBDID_DATA); /* data hi sets stop */
08928     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK ); /* data low sets start (now reset) */
08929     edt_intfc_write(edt_p, MEZZANINE_BD_ID, 0); /* clock low */
08930     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /* drive data high in prep for ts */
08931     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* tristate while data hi*/
08932 
08933     /* a few extra clocks to complete reset */
08934 
08935     for(init = 2; init > 0; --init)
08936     {
08937         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_CLK);
08938         edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS);
08939     }
08940     /* CPLD should be idle, clock low and data tristate (pulled up high) */
08941     /* force another start */
08942 
08943     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* make data hi before enable*/
08944     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /*  enable FPGS on data bus */
08945     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK | EDT_EXTBDID_DATA); /* set clock hi */
08946     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_CLK ); /* data low while clock high sets start */
08947     edt_intfc_write(edt_p, MEZZANINE_BD_ID, 0); /* clock low */
08948     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_DATA); /*  data hi in prep for ts */
08949     edt_intfc_write(edt_p, MEZZANINE_BD_ID, EDT_EXTBDID_TS | EDT_EXTBDID_DATA); /* ts data */
08950 
08951 }
08952 
08999 u_int
09000 edt_get_full_board_id(EdtDev *edt_p, int *extended_n, int *rev_id, u_int *extended_data)
09001 {
09002     u_int mezz_id;              /* board id from mezannine */
09003     int board_id = 0;           /* board id read back from cpld. initialized to 0 */
09004     int num_blocks = 0;         /* number of 32 bit blocks to read from cpld. initialized to 0 */
09005     int ext_info = 0;
09006     int ext_data_index = 0;
09007     int tries = 2;
09008     int store = 1;
09009     int try_3x3g = 1;
09010 
09011     /* once id is set, go ahead and return */
09012     if (edt_p->mezz.id == MEZZ_ID_UNKNOWN)
09013     {
09014 
09015         /* check whether it's set in the driver */
09016 
09017         edt_get_mezz_id(edt_p);
09018 
09019         edt_msleep(1);
09020 
09021         if (edt_p->mezz.id == MEZZ_ID_UNKNOWN)
09022         {
09023 
09024 
09025             /* Read the Board ID register and determine if it is extended */
09026 
09027             mezz_id = edt_intfc_read(edt_p, MEZZANINE_BD_ID);
09028             if ((mezz_id & 0x1f) == 0x12)
09029             {
09030                 /* for 3x3g case, force to use "standard" extbdid pins. */
09031                 edt_intfc_write(edt_p, (INTFC_BYTE | 0x84), 0x00);
09032                 printf("edt_get_full_board_id: First time since driver load\n");
09033                 board_id = -1;
09034 
09035 
09036                 while (tries && board_id == -1)
09037                 {
09038 
09039                     /* resetthe CPLD and start a read */
09040                     /* data is tristate and clock is low when finished */
09041 
09042                     edt_extbdid_reset(edt_p);
09043 
09044                     /* clock the cpld 32 times to get the first 32 bits of data. Data is valid on falling edge */
09045                     /* The first 12 bits are the number of 32 bit words, the next 12 are the board id, and the  */
09046                     /* last 8 is the board revision id. */
09047 
09048                     ext_info = edt_read_extbdid_val(edt_p);
09049 
09050                     /* calculate the number of 32 bit blocks */
09051 
09052                     num_blocks = ext_info >> 20;
09053                     if(num_blocks >= 1 && num_blocks <= MAX_EXTENDED_WORDS)
09054                     {
09055                         board_id = (ext_info >> 8) & 0xfff;
09056 
09057                         if (rev_id)
09058                             *rev_id = ext_info & 0xff;
09059                         edt_p->mezz.extended_rev = ext_info & 0xff;
09060                     }
09061                     else
09062                     {
09063 
09064                         tries--;
09065                         edt_extbdid_stop(edt_p);
09066                         num_blocks = 0;
09067                         edt_msg(EDTWARN, "Warning: bitstream error during extended board id lookup?\n");
09068                         /* for 3x3g case: */
09069                         if (tries == 0 && try_3x3g == 1){
09070                             edt_msg(EDTWARN, "Warning: attempting to detect 3x3g.\n");
09071                             /* force to use "3x3g" extbdid pins. */
09072                             edt_intfc_write(edt_p, (INTFC_BYTE | 0x84), 0x01);
09073                             /* retry and flag as having tried 3x3g. */
09074                             tries = 2;
09075                             try_3x3g = 0;
09076                         }
09077                     }
09078 
09079                 }
09080 
09081                 /* read all the additional 32 bit blocks back from the cpld  */
09082                 for (ext_data_index = 0; ext_data_index < num_blocks - 1;
09083                     ext_data_index ++)
09084                 {
09085                     ext_info = edt_read_extbdid_val(edt_p);
09086 
09087                     if (extended_data)
09088                         extended_data[ext_data_index] = ext_info;
09089                     edt_p->mezz.extended_data[ext_data_index] = ext_info;
09090 
09091                 }
09092 
09093                 edt_extbdid_stop(edt_p);
09094 
09095             }
09096 
09097             /* board id is extended, but UI bitfile does not support this functionality. Need to load  */
09098             /* the correct bitfile */
09099             else if(mezz_id == 0x02)
09100             {
09101                 /* TODO:  error handling */
09102                 board_id = (mezz_id);
09103                 store = 0;
09104             }
09105 
09106             /* No bitfile loaded. Need to load a bitfile supporting extended
09107             * board id. */
09108             else if (mezz_id == 0xcc)
09109             {
09110                 /* TODO:  error handling */
09111                 board_id = (mezz_id);
09112                 store = 0;
09113             }
09114 
09115             /* board ID is the lower 4 bits of MEZZANINE_BD_ID register. No extended information is available. */
09116             else if (mezz_id != 0xff)
09117             {
09118                 board_id = (mezz_id & 0x0f);
09119             }
09120             else
09121             {
09122                 store = 0;
09123             }
09124 
09125 
09126             if (store)
09127             {
09128                 edt_p->mezz.id = board_id;
09129                 edt_p->mezz.n_extended_words = num_blocks-1;
09130                 edt_set_mezz_id(edt_p);
09131             }
09132         }
09133     }
09134 
09135     /* fill in arguments */
09136     /* redundant now that info is store in edt_p */
09137 
09138     if (extended_n)
09139         *extended_n = edt_p->mezz.n_extended_words;
09140     if (rev_id)
09141         *rev_id = edt_p->mezz.extended_rev;
09142     if (extended_data)
09143         memcpy(extended_data, edt_p->mezz.extended_data, sizeof(edt_p->mezz.extended_data));
09144 
09145     return edt_p->mezz.id;
09146 
09147 }
09148 
09163 u_int
09164 edt_get_board_id(EdtDev *edt_p)
09165 {
09166     return edt_get_full_board_id(edt_p, NULL, NULL, NULL);
09167 }
09168 
09169 
09170 int
09171 edt_set_ignore_signals(EdtDev *edt_p, int ignore)
09172 {
09173     return edt_ioctl(edt_p, EDTS_IGNORE_SIGNALS, &ignore);
09174 }
09175 
09184 void
09185 edt_set_trace_regs(EdtDev *edt_p, u_int reg_def, u_int state)
09186 
09187 {
09188     /* we pass the trace state in the upper bit of reg_def */
09189     u_int reg_def_mask = (state) ? reg_def | 0x80000000 : reg_def;
09190 
09191     edt_ioctl(edt_p, EDTS_TRACE_REG, &reg_def_mask);
09192 
09193 }
09194 
09195 /* Turn on global flag for tracing register accesses.
09196 * Individual registers or register types must still be enabled
09197 * using edt_set_trace_regs */
09198 
09199 void
09200 edt_trace_regs_enable(EdtDev *edt_p, u_int state)
09201 
09202 {
09203     u_int reg_def_mask = (state) ? 1 : 0 ;
09204 
09205     edt_ioctl(edt_p, EDTS_TRACE_REG, &reg_def_mask);
09206 
09207 }
09208 
09209 void
09210 edt_set_intr_mask(EdtDev *edt_p, u_int state)
09211 
09212 {
09213     edt_ioctl(edt_p, EDTS_INTR_MASK, &state);
09214 }
09215 
09216 u_int
09217 edt_get_intr_mask(EdtDev *edt_p)
09218 
09219 {
09220     u_int state = 0;
09221     edt_ioctl(edt_p, EDTG_INTR_MASK, &state);
09222     return state;
09223 }
09224 
09225 void
09226 edt_set_remote_intr(EdtDev *edt_p, u_int onoff)
09227 
09228 {
09229     u_int current;
09230     current = edt_get_intr_mask(edt_p);
09231 
09232     current = (current & ~EDT_ICFG_RMT_EN_INTR) ;
09233     current |= (onoff)?EDT_ICFG_RMT_EN_INTR | EDT_ICFG_PCI_EN_INTR:0;
09234 
09235     edt_set_intr_mask(edt_p, current);
09236 }
09237 
09238 u_int
09239 edt_get_remote_intr(EdtDev *edt_p)
09240 
09241 {
09242     return (edt_get_intr_mask(edt_p) & EDT_ICFG_RMT_EN_INTR) != 0;
09243 }
09244 
09245 
09254 int edt_set_sync_interval(EdtDev *edt_p, u_int interval)
09255 
09256 {
09257     edt_ioctl(edt_p, EDTS_SYNC_INTERVAL, &interval);
09258     return 0;
09259 }
09260 
09261 
09275 int
09276 edt_enable_channels(EdtDev *edt_p, u_int mask)
09277 {
09278 
09279     switch (edt_p->devid)
09280     {
09281         case PE8LX32_ID:
09282         case PE8G2V7_ID:
09283             edt_reg_or(edt_p, SSD16_CHEN32, mask);
09284             break;
09285 
09286         default:
09287             edt_reg_or(edt_p, SSD16_CHEN, mask);
09288             break;
09289     }
09290 
09291     return 0;
09292 }
09293 
09294 
09308 int
09309 edt_disable_channels(EdtDev *edt_p, u_int mask)
09310 {
09311 
09312     switch (edt_p->devid)
09313     {
09314         case PE8LX32_ID:
09315         case PE8G2V7_ID:
09316             edt_reg_and(edt_p, SSD16_CHEN32, ~mask);
09317             break;
09318 
09319         default:
09320             edt_reg_and(edt_p, SSD16_CHEN, ~mask);
09321             break;
09322     }
09323 
09324 
09325     return 0;
09326 }
09327 
09341 int
09342 edt_enable_channel(EdtDev *edt_p, u_int channel)
09343 {
09344 
09345     u_int enable_bit = 1 << channel;
09346 
09347     switch (edt_p->devid)
09348     {
09349         case PE8LX32_ID:
09350         case PE8G2V7_ID:
09351             edt_reg_or(edt_p, SSD16_CHEN32, enable_bit);
09352             break;
09353 
09354         default:
09355             edt_reg_or(edt_p, SSD16_CHEN, enable_bit);
09356             break;
09357     }
09358 
09359     return 0;
09360 }
09361 
09362 
09363 
09377 int
09378 edt_disable_channel(EdtDev *edt_p, u_int channel)
09379 {
09380 
09381     u_int enable_bit = 1 << channel;
09382 
09383     switch (edt_p->devid)
09384     {
09385         case PE8LX32_ID:
09386         case PE8G2V7_ID:
09387             edt_reg_and(edt_p, SSD16_CHEN32, ~enable_bit);
09388             break;
09389 
09390         default:
09391             edt_reg_and(edt_p, SSD16_CHEN, ~enable_bit);
09392             break;
09393     }
09394 
09395     return 0;
09396 }
09397 
09415 u_int
09416 edt_bar1_read(EdtDev * edt_p, u_int offset)
09417 {
09418     u_int   val;
09419 
09420     val = edt_reg_read(edt_p, EDT_BAR1_REGISTER | (offset & 0x0ffffffc));
09421 
09422     return val;
09423 }
09424 
09444 void
09445 edt_bar1_write(EdtDev * edt_p, u_int offset, u_int data)
09446 {
09447     edt_reg_write(edt_p, EDT_BAR1_REGISTER | (offset & 0x0ffffffc), data);
09448 }
09449 
09450 
09468 unsigned int
09469 edt_lcr_read(EdtDev *edt_p, unsigned int regBlock, unsigned int regOffset)
09470 {
09471 
09472     unsigned int regAddr = LCR_DDC_REG_SPACE | ((regBlock & 0x7F) << 12) | (regOffset & 0xFFF);
09473 
09474     return edt_bar1_read(edt_p, regAddr);
09475 
09476 }
09477 
09478 
09479 
09499 void
09500 edt_lcr_write(EdtDev *edt_p, unsigned int regBlock, unsigned int regOffset, unsigned int regVal)
09501 {
09502 
09503     unsigned int regAddr = LCR_DDC_REG_SPACE | ((regBlock & 0x7F) << 12) | (regOffset & 0xFFF);
09504 
09505     edt_bar1_write(edt_p, regAddr, regVal);
09506 
09507 }
09508 
09509 
09514 void
09515 edt_set_port(EdtDev *edt_p, int port)
09516 
09517 {
09518     edt_p->port_no = port;
09519 }
09523 int
09524 edt_get_port(EdtDev *edt_p)
09525 
09526 {
09527     return edt_p->port_no;
09528 }
09529 
09530 
09544 uint_t
09545 edt_ind_2_read(EdtDev * edt_p, uint_t desc, u_int *width)
09546 {
09547     int     ret;
09548     edt_buf buf = {0, 0};
09549 
09550     buf.desc = desc;
09551     if (width)
09552         buf.flags = *width;
09553 
09554     ret = edt_ioctl(edt_p, EDTG_IND_2_REG, &buf);
09555     if (ret < 0)
09556         return ret;
09557 
09558     if (width)
09559         *width = buf.flags;
09560 
09561     return (u_int) buf.value;
09562 }
09563 
09577 uint_t
09578 edt_ind_2_write(EdtDev * edt_p, uint_t desc, u_int value, u_int *width)
09579 {
09580     int     ret;
09581     edt_buf buf = {0, 0};
09582 
09583     buf.desc = desc;
09584     buf.value = value;
09585 
09586     if (width)
09587         buf.flags = *width;
09588 
09589     ret = edt_ioctl(edt_p, EDTS_IND_2_REG, &buf);
09590     if (ret < 0)
09591         return -1;
09592 
09593     if (width)
09594         *width = buf.flags;
09595 
09596     return (uint_t) buf.value;
09597 
09598 }
09599 
09600 
09619 #ifdef WIN32
09620 #include <direct.h>
09621 #endif
09622 
09623 static char pwd_home[MAXPATH];
09624 
09625 const char *edt_home_dir(EdtDev *edt_p)
09626 {
09627 
09628     const char *s = edt_envvar_from_devtype(edt_p->devtype);
09629 
09630     if (s)
09631         return s;
09632 
09633     s = getcwd(pwd_home, MAXPATH-1);
09634     if (!s)
09635         s = ".";
09636     return s;
09637 
09638 }
09639 
09640 const char *edt_envvar_from_devstr(const char *devstr)
09641 {
09642     const char *s;
09643     if (strcmp(devstr,"pcd") == 0)
09644         if (s = getenv("PCDHOME"))
09645             return s;
09646     if (strcmp(devstr,"pdv") == 0)
09647         if (s = getenv("PDVHOME"))
09648             return s;
09649     if (strcmp(devstr,"p11w") == 0)
09650         if (s = getenv("P11wHOME"))
09651             return s;
09652     if (strcmp(devstr,"p16d") == 0)
09653         if (s = getenv("P16dHOME"))
09654             return s;
09655     if (strcmp(devstr,"p53b") == 0)
09656         if (s = getenv("P53bHOME"))
09657             return s;
09658 
09659     return NULL;
09660 }
09661 
09662 const char *edt_envvar_from_devtype(const int devtype)
09663 {
09664     const char *s;
09665     const char *ret;
09666 
09667     switch (devtype)
09668     {
09669         case pcd:
09670             if (s = getenv("PCDHOME"))
09671                 ret = s;
09672             else ret = NULL;
09673             break;
09674         case pdv:
09675             if (s = getenv("PDVHOME"))
09676                 ret = s;
09677             else ret = NULL;
09678             break;
09679         case p11w:
09680             if (s = getenv("P11wHOME"))
09681                 ret = s;
09682             else ret = NULL;
09683             break;
09684         case p16d:
09685             if (s = getenv("P16dHOME"))
09686                 ret = s;
09687             else ret = NULL;
09688             break;
09689         case p53b:
09690             if (s = getenv("P53bHOME"))
09691                 ret = s;
09692             else ret = NULL;
09693             break;
09694         default:
09695             ret = NULL;
09696     }
09697     return ret;
09698 }

Generated on 19 Jun 2015 by  doxygen 1.4.7