libedt.c

00001 
00002 /* #pragma ident "@(#)libedt.c  1.396 05/29/07 EDT" */
00003 
00004 #include "edtinc.h"
00005 
00006 #if defined(__linux__) || defined(__APPLE__)
00007 #include <unistd.h>
00008 #include <sys/mman.h>
00009 #include <sys/time.h>
00010 #include <sys/resource.h>
00011 #endif
00012 
00013 #include <stdlib.h>
00014 #include <ctype.h>
00015 
00016 #ifndef _NT_
00017 #include <sys/ioctl.h>
00018 #endif
00019 
00020 #ifdef VXWORKS
00021 #include "vmLib.h"
00022 #include "cacheLib.h"
00023 extern int sysGetVmPageSize();
00024 #endif
00025 
00026 #ifdef _NT_
00027 
00028 #include <process.h>
00029 
00030 #else
00031 
00032 #ifndef VXWORKS
00033 #include <sys/errno.h>
00034 #endif
00035 
00036 #endif
00037 
00038 #ifdef __sun
00039 #include <thread.h>
00040 #endif
00041 #ifdef __sun
00042 #include <sys/mman.h>
00043 #endif
00044 #ifdef __sun
00045 #include <sys/priocntl.h>
00046 #include <sys/rtpriocntl.h>
00047 #include <sys/tspriocntl.h>
00048 #endif
00049 
00050 #if defined(_NT_)
00051 #include <process.h>
00052 #elif defined(__sun) || defined(__linux__) || defined(__APPLE__)
00053 #include <sys/wait.h>
00054 #endif
00055 
00056 
00057 #ifndef PAGE_SHIFT
00058 #define PAGE_SHIFT (12)
00059 #endif
00060 
00061 #ifndef PAGE_SIZE
00062 #define PAGE_SIZE (1UL << PAGE_SHIFT)
00063 #endif
00064 
00065 #ifndef PAGE_MASK
00066 #define PAGE_MASK (PAGE_SIZE-1)
00067 #endif
00068 
00069 
00070 /*
00071 * EDT Library
00072 * 
00073 * Copyright (c) 1998, 2005 by Engineering Design Team, Inc.
00074 * 
00075 * DESCRIPTION Provides a 'C' language   interface to the EDT PCI DMA cards
00076 * to simplify the       ring buffer method of reading data.
00077 * 
00078 * All routines access a specific device, whose handle is created and returned
00079 * by    the edt_open() routine.
00080 * 
00081 */
00082 
00083 /* support for dmy device */
00084 static u_int dmy_started = 0 ;
00085 
00086 
00087 int dump_reg_access = 0;
00088 
00089 void edt_set_dump_reg_access(int on)
00090 
00091 {
00092     dump_reg_access = on;
00093 }
00094 
00095 #ifndef _NT_
00096 
00097 extern int errno;
00098 
00099 static void
00100 edt_set_errno(int val)
00101 
00102 {
00103     errno = val;
00104 }
00105 
00106 #else
00107 
00108 #define edt_set_errno(val)
00109 
00110 #endif
00111 
00112 
00113 
00114 int edt_clear_wait_status(EdtDev *edt_p);
00115 
00116 #ifndef SECTOR_SIZE
00117 #define SECTOR_SIZE 512
00118 #endif
00119 
00120 #ifndef PAGESIZE
00121 #define PAGESIZE 4096
00122 #endif
00123 
00124 #define DEFAULT_BUFFER_GRANULARITY PAGESIZE
00125 #define MINHEADERSIZE SECTOR_SIZE
00126 /* shorthand debug level */
00127 #define EDTDEBUG EDTLIB_MSG_INFO_2
00128 #define EDTFATAL EDTLIB_MSG_FATAL
00129 #define EDTWARN EDTLIB_MSG_WARNING
00130 
00131 #if defined(__APPLE__)
00132 void *edt_mac_open(char *classname, int unit, int channel);
00133 void *edt_mac_ioctl(void *dataPort, int code, void *eis);
00134 #endif
00135 
00136 #ifdef _NT_
00137 static u_int WINAPI 
00138 edt_wait_event_thread(void *);
00139 
00140 int
00141 edt_get_kernel_event(EdtDev *edt_p, int event_num);
00142 static
00143 void
00144 edt_clear_event_func(EdtEventHandler * p);
00145 
00146 #else
00147 static void *
00148 edt_wait_event_thread(void *);
00149 
00150 #endif
00151 
00152 static char *BaseEventNames[] =
00153 {
00154     NULL,
00155     EDT_EODMA_EVENT_NAME,
00156     EDT_BUF_EVENT_NAME,
00157     EDT_STAT_EVENT_NAME,
00158     EDT_P16D_DINT_EVENT_NAME,
00159     EDT_P11W_ATTN_EVENT_NAME,
00160     EDT_P11W_CNT_EVENT_NAME,
00161     EDT_PDV_ACQUIRE_EVENT_NAME,
00162     EDT_EVENT_PCD_STAT1_NAME,
00163     EDT_EVENT_PCD_STAT2_NAME,
00164     EDT_EVENT_PCD_STAT3_NAME,
00165     EDT_EVENT_PCD_STAT4_NAME,
00166     EDT_PDV_STROBE_EVENT_NAME,
00167     EDT_EVENT_P53B_SRQ_NAME,
00168     EDT_EVENT_P53B_INTERVAL_NAME,
00169     EDT_EVENT_P53B_MODECODE_NAME,
00170     EDT_EVENT_P53B_DONE_NAME,
00171     EDT_PDV_EVENT_FVAL_NAME,
00172     EDT_PDV_EVENT_TRIGINT_NAME,
00173     EDT_EVENT_TEMP_NAME,
00174     NULL
00175 };
00176 
00177 #ifdef USB
00178 
00186 u_int
00187 usb_reg_read (EdtDev *edt_p, u_int desc)
00188 {
00189     int i, addr;
00190     u_int retval = 0 ;
00191     unsigned char setup[3];
00192     unsigned char buf[5];
00193     int bytes;
00194 
00195     if (usb_claim_interface(edt_p->usb_p, 0) < 0)
00196     {
00197         edt_set_errno(EBUSY); ;
00198         return 0 ;
00199     }
00200 
00201     addr = EDT_REG_ADDR(desc) ;
00202 
00203     for (i = 0; i < EDT_REG_SIZE(desc); i++)
00204     {
00205         setup[0] = 0x03 ;
00206         setup[1] = addr ;
00207 
00208         /* Send setup bytes */
00209         if ((usb_bulk_write(edt_p->usb_p, 0x01, setup, 2,
00210             edt_p->usb_rtimeout)) < 0) 
00211         {
00212             usb_release_interface(edt_p->usb_p, 0);
00213             edt_set_errno(EINVAL); ;
00214             return 0 ;
00215         }
00216 
00217         /* Read back setup bytes to verify */
00218         bytes = usb_bulk_read(edt_p->usb_p, 0x81, buf, 1, edt_p->usb_rtimeout);
00219 
00220         if (bytes < 1)
00221         {
00222             extern int errno ;
00223             usb_release_interface(edt_p->usb_p, 0);
00224             edt_set_errno(EINVAL); ;
00225             return 0 ;
00226         }
00227 
00228         ++addr ;
00229         retval |= ((u_int) buf[0] << (i * 8)) ;
00230     }
00231 
00232     usb_release_interface(edt_p->usb_p, 0);
00233 
00234     return retval ;
00235 }
00236 
00244 void
00245 usb_reg_write(EdtDev *edt_p, u_int desc, u_int value)
00246 {
00247     int i, addr, size;
00248     unsigned char setup[4];
00249     unsigned char buf[4];
00250 
00251     if (usb_claim_interface(edt_p->usb_p, 0) < 0)
00252     {
00253         edt_set_errno(EBUSY); ;
00254         return ;
00255     }
00256 
00257     addr = EDT_REG_ADDR(desc) ;
00258 
00259     for (i = 0; i < EDT_REG_SIZE(desc); i++)
00260     {
00261         if (EDT_REG_TYPE(desc) == REMOTE_USB_TYPE)
00262         {
00263             setup[0] = 0x04;
00264             setup[1] = addr ;
00265             setup[2] = value & 0xff ;
00266             size = 3 ;
00267         }
00268         else if (EDT_REG_TYPE(desc) == LOCAL_USB_TYPE)
00269         {
00270             setup[0] = 0x01;
00271             setup[1] = value & 0xff ;
00272             size = 2 ;
00273         }
00274 
00275         /* Send setup bytes */
00276         if ((usb_bulk_write(edt_p->usb_p, 0x01, setup, size,
00277             edt_p->usb_wtimeout)) < 0) 
00278         {
00279             usb_release_interface(edt_p->usb_p, 0);
00280             edt_set_errno(EINVAL); ;
00281             return ;
00282         }
00283 
00284         addr++ ;
00285         value >>= 8 ;
00286     }
00287 
00288     usb_release_interface(edt_p->usb_p, 0);
00289 }
00290 
00291 
00292 /*
00293 * find the EDT USB board attached
00294 */
00295 struct usb_device *edt_find_usb_board(int unit)
00296 {
00297     struct usb_bus *p;
00298     struct usb_device *q;
00299 
00300     for (p = usb_busses; p; p = p->next)
00301     {
00302         q = p->devices;
00303         while(q)
00304         {
00305             if ((q->descriptor.idVendor==0x04b4) &&
00306                 (q->descriptor.idProduct=0x8613))
00307                 return q;
00308             else
00309                 q = q->next;
00310         }
00311     }
00312 
00313     return NULL;
00314 }
00315 #endif /* USB */
00316 
00317 int edt_driver_type = -1;
00318 
00319 static int             edt_parse_devname(EdtDev *edt_p, char *edt_devname, int unit, int channel);
00320 
00321 
00322 EdtDev *edt_open_device(char *device_name, int unit, int channel, int verbose)
00323 
00324 {
00325     EdtDev *edt_p;              /* ptr video device struct */
00326     static char *debug_env = NULL;
00327     u_int   dmy;
00328     int edt_debug;
00329     static char *debug_file = NULL;
00330     int level;
00331 
00332     if ((debug_env == NULL)
00333         && ((debug_env = (char *) getenv("EDTDEBUG")) != NULL)
00334         && *debug_env != '0')
00335     {
00336         edt_debug = atoi(debug_env);
00337         level = edt_msg_default_level();
00338         if (edt_debug > 0) 
00339         {
00340             level |= EDTLIB_MSG_INFO_1;
00341             level |= EDTLIB_MSG_INFO_2;
00342         }
00343         edt_msg_set_level(edt_msg_default_handle(), level);
00344 
00345         if ((debug_file == NULL)
00346             && ((debug_file = (char *) getenv("EDTDEBUGFILE")) != NULL)
00347             && *debug_file != '0')
00348         {
00349             edt_msg_set_name(edt_msg_default_handle(), debug_file);
00350         }
00351 
00352         edt_msg(EDTDEBUG, "environment DEBUG set to %d: enabling debug in edtlib\n", edt_debug);
00353     }
00354 
00355     if ((edt_p = (EdtDev *) calloc(1, sizeof(EdtDev))) == NULL)
00356     {
00357         char errstr[128];
00358         sprintf(errstr, "edtlib: malloc (%lx) in edt_open failed\n", sizeof(EdtDev));
00359         edt_msg_perror(EDTWARN, errstr);
00360         return (NULL);
00361     }
00362 
00363     if(verbose)
00364         edt_msg(EDTDEBUG, "edt_open_device(%s, %d)\n", device_name, unit);
00365 
00366     if ((strncmp(device_name, "dmy", 3) == 0) || (strncmp(device_name, "DMY", 3) == 0))
00367         edt_p->devid = DMY_ID;
00368 #ifdef USB
00369     else if (strncasecmp(device_name, "usb", 3) == 0)
00370         edt_p->devtype = USB_ID; /* Set until true ID retrieved from device */
00371 #endif
00372 
00373 
00374     if (edt_parse_devname(edt_p, device_name, unit, channel) != 0)
00375     {
00376         edt_msg(EDTFATAL, "Illegal EDT device name (edt_open_device):  %s\n", device_name);
00377         return NULL;
00378     }
00379 
00380     edt_p->unit_no = unit;
00381     edt_p->channel_no = channel;
00382 
00383 #ifdef USB
00384     if (edt_p->devtype == USB_ID)
00385     {
00386         struct usb_device *current_device = NULL;
00387 
00388         usb_init();
00389         usb_find_busses();
00390         usb_find_devices();
00391 
00392         current_device = edt_find_usb_board(unit);
00393 
00394         if(current_device==NULL)
00395         {
00396             edt_set_errno(ENODEV); ;
00397             return NULL;
00398         } 
00399 
00400         edt_p->usb_p = usb_open(current_device);
00401 
00402         /*
00403         * The following assume that large buffer reads occur
00404         * on endpoints 82, 84, 86, and 88.  82 is channel 2,
00405         * 84 channel 1, etc.  Large buffer writes occur on
00406         * endpoints 2, 4, 6, and 8.
00407         */
00408         edt_p->usb_bulk_read_endpoint = 0x80 + (channel * 2) + 2 ;
00409         edt_p->usb_bulk_write_endpoint = (channel * 2) + 2 ;
00410 
00411     }
00412     else
00413 #endif
00414     {
00415 
00416 #ifdef _NT_
00417         edt_p->fd = CreateFile(edt_p->edt_devname,
00418             GENERIC_READ | GENERIC_WRITE,
00419             FILE_SHARE_READ | FILE_SHARE_WRITE,
00420             NULL,
00421             edt_p->devid == (DMY_ID) ? OPEN_ALWAYS 
00422             : OPEN_EXISTING,
00423             FILE_ATTRIBUTE_NORMAL,
00424             NULL);
00425 
00426         if (edt_p->fd == INVALID_HANDLE_VALUE)
00427         {
00428             if (verbose)
00429                 edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", device_name);
00430 
00431             return (NULL);
00432         }
00433 #else
00434 #if defined (__APPLE__)
00435         /* dataPort = edt_mac_open("pcd",0) ;*/
00436         if (verbose)
00437             edt_msg(EDTWARN, "edt_devname %s unit %d channel %d\n",edt_p->edt_devname,unit,channel) ;
00438         if (edt_p->devid != DMY_ID)
00439         {
00440             if ((edt_p->fd = edt_mac_open(edt_p->edt_devname, unit, channel)) <= 0 )
00441             {
00442                 if (verbose)
00443                     edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00444                 return (NULL);
00445             }
00446             {
00447                 edt_ioctl(edt_p, EDTG_DEVID, &edt_p->devid);
00448                 if (edt_is_pdv(edt_p))
00449                 {
00450                     if (strncmp(device_name, "pdv", 3) != 0)
00451                     {
00452                         if (verbose)
00453                             printf("%s not match for pdv\n",edt_p->edt_devname) ;
00454                         close(edt_p->fd) ;
00455                         return(NULL);
00456                     }
00457                 }
00458                 else if (edt_is_pcd(edt_p))
00459                 {
00460                     if (strncmp(device_name, "pcd", 3) != 0)
00461                     {
00462                         if (verbose)
00463                             printf("%s not match for pcd\n",edt_p->edt_devname) ;
00464                         close(edt_p->fd) ;
00465                         return(NULL);
00466                     }
00467                 }
00468             }
00469         }
00470         else
00471         {
00472             if (!edt_p->fd)
00473             {
00474                 if ((edt_p->fd = open(edt_p->edt_devname, O_RDWR|O_CREAT, 0666)) < 0 )
00475                 {
00476                     if (verbose)
00477                         edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00478                     return (NULL);
00479                 }
00480             }
00481             /* printf("skipping open with fd already open\n") ;*/
00482         }
00483 #else
00484 
00485         if ((edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666)) < 0 )
00486         {
00487             if (verbose)
00488                 edt_msg(EDTWARN, "EDT %s open failed.\nCheck board installation and unit number, and try restarting the computer\n", edt_p->edt_devname);
00489             return (NULL);
00490         }
00491         /* make sure fd not carried across exec */
00492 #if defined( __linux__) || defined(__sun)
00493         fcntl(edt_p->fd, F_SETFD, FD_CLOEXEC);
00494 #endif
00495 
00496 #endif /* not apple */
00497 #endif
00498     }
00499 
00500 
00501 
00502     edt_msg(EDTDEBUG, "edt_open for %s unit %d succeeded\n", device_name, unit);
00503 
00504     if (edt_p->devid != DMY_ID)
00505     {
00506         edt_ioctl(edt_p, EDTG_DEVID, &edt_p->devid);
00507         edt_ioctl(edt_p, EDTS_RESETCOUNT, &dmy);
00508         dmy = edt_p->foi_unit ;
00509         edt_ioctl(edt_p, EDTS_RESETSERIAL, &dmy);
00510 
00511 #ifdef _NT_
00512         edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
00513         edt_get_kernel_event(edt_p, EDT_EVENT_STAT);
00514         if (edt_p->devid == P53B_ID)
00515         {
00516             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_SRQ);
00517             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_INTERVAL);
00518             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_MODECODE);
00519             edt_get_kernel_event(edt_p, EDT_EVENT_P53B_DONE);
00520         }
00521 #endif
00522     }
00523 
00524     edt_p->donecount = 0;
00525     edt_p->tmpbuf = 0;
00526     edt_p->dd_p = 0;
00527     edt_p->b_count = 0;
00528     edt_p->buffer_granularity = DEFAULT_BUFFER_GRANULARITY;
00529     edt_p->mezz.id = MEZZ_ID_UNKNOWN;
00530 
00531     edt_driver_type = edt_get_drivertype(edt_p);
00532 
00533     return edt_p;
00534 }
00535 
00536 
00560 EdtDev *
00561 edt_open(char *device_name, int unit)
00562 {
00563 
00564     return edt_open_device(device_name, unit, 0, 1);
00565 }
00566 
00567 
00581 EdtDev *
00582 edt_open_quiet(char *device_name, int unit)
00583 {
00584     return edt_open_device(device_name, unit, 0, 0); 
00585 }
00586 
00614 EdtDev *
00615 edt_open_channel(char *device_name, int unit, int channel)
00616 {
00617     return edt_open_device(device_name, unit, channel, 1); 
00618 }
00619 
00628 static int
00629 edt_parse_devname(EdtDev *edt_p, char *device_name, int unit, int channel)
00630 {
00631 
00632     char *format;
00633 
00634     char dev_string[512];
00635 
00636     if (!device_name)
00637         return -1;
00638 
00639     if (device_name[0] == '\\' || device_name[0] == '/')
00640     {
00641         strcpy(edt_p->edt_devname, device_name);
00642     }
00643     else if (edt_p->devid == DMY_ID)
00644     {
00645 #ifdef _NT_
00646         format = ".\\%s%d" ;
00647 #else
00648         format = "./%s%d" ;
00649 #endif
00650         (void) sprintf(edt_p->edt_devname, format, device_name, unit) ;
00651     }
00652     else
00653     {
00654         int i;
00655 
00656         strncpy(dev_string, device_name,511);
00657 
00658         for (i=0;dev_string[i]; i++)
00659             dev_string[i] = tolower(dev_string[i]);
00660 
00661 #ifdef _NT_
00662         dev_string[0] = toupper(dev_string[0]);
00663 #endif
00664 
00665 #if defined(__linux__)
00666         if (strcmp(dev_string, "pcd") == 0)
00667             strcpy(dev_string, "pcicd");
00668 #endif
00669 
00670 
00671 #ifdef _NT_
00672         if (channel > 0)
00673         {
00674             format = "\\\\.\\%s%d_%d"; 
00675         } 
00676         else
00677         {
00678             format = "\\\\.\\%s%d";
00679         }
00680 #else
00681         if (channel > 0)
00682         {
00683             format = "/dev/%s%d_%d"; 
00684         } 
00685         else
00686         {
00687             format = "/dev/%s%d";
00688         }
00689 #endif
00690         (void) sprintf(edt_p->edt_devname, format, dev_string, unit, channel);
00691 
00692     }
00693     edt_msg(EDTDEBUG, "parse open to %s\n",edt_p->edt_devname) ;
00694 
00695     return 0;
00696 }
00697 
00708 int
00709 edt_close(EdtDev *edt_p)
00710 
00711 {
00712     u_int   i;
00713 #ifdef __sun
00714     EdtEventHandler *p;
00715 #endif
00716 
00717     edt_msg(EDTDEBUG, "edt_close()\n");
00718 
00719     for (i = 0; i < EDT_MAX_KERNEL_EVENTS; i++)
00720     {
00721 
00722 
00723 #ifdef __sun
00724         p = &edt_p->event_funcs[i];
00725         if (p->active)
00726         {
00727             p->active = 0;
00728 
00729             edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &i);
00730             edt_ioctl(p->owner, EDTS_CLR_EVENT, &i);
00731             sema_destroy(&p->sema_thread);
00732             thr_join(NULL, NULL, NULL);
00733         }
00734 #else
00735 #ifndef NO_PTHREAD
00736 
00737         edt_remove_event_func(edt_p, i);
00738 #endif
00739 #endif
00740     }
00741 
00742     if (edt_p->ring_buffers_configured)
00743         edt_disable_ring_buffers(edt_p);
00744 
00745     if (edt_p->fd)
00746     {
00747 #ifdef _NT_
00748         CloseHandle(edt_p->fd);
00749 #else
00750 #if defined (__APPLE__)
00751         edt_mac_close(edt_p->fd) ;
00752 #else
00753         close(edt_p->fd);
00754 #endif
00755 #endif
00756     }
00757     free(edt_p);
00758 
00759     return 0;
00760 }
00761 
00773 unsigned char *
00774 edt_alloc(int size)
00775 {
00776     unsigned char *ret;
00777 
00778 #ifdef _NT_
00779     ret = (unsigned char *)
00780         VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
00781 #else
00782 #if defined(AV3_BOARD) || defined(XCALIBURCOMMON)
00783     ret = (unsigned char *) edt_vmalloc(size);
00784 #else
00785     ret = (unsigned char *) valloc(size);
00786 #if defined(__linux__) || defined(sgi) || defined(VXWORKS)
00787     if (ret)
00788     {
00789         u_char *tmp_p;
00790 
00791         for (tmp_p = ret; tmp_p < ret + size; tmp_p += 4096)
00792         {
00793             /* edt_msg(EDTDEBUG, "touching %x\n",tmp_p) ; */
00794             *tmp_p = 0xa5;
00795         }
00796     }
00797 #endif
00798 #endif
00799 
00800 #endif
00801     return (ret);
00802 }
00803 
00812 void
00813 edt_free(uchar_t *ptr)
00814 {
00815 #ifdef _NT_
00816     VirtualFree(ptr, 0, MEM_RELEASE);
00817 #else
00818 #if defined(AV3_BOARD) || defined(XCALIBURCOMMON)
00819     edt_vfree(ptr);
00820 #else
00821     free(ptr);
00822 #endif
00823 #endif
00824 }
00825 
00826 
00827 #ifdef __sun
00828 
00829 typedef struct
00830 {
00831     uint_t  index;
00832     uint_t  writeflag;
00833     EdtDev *edt_p;
00834 }       thr_buf_args;
00835 
00836 static void *
00837 aio_thread(   void   *arg)
00838 
00839 {
00840     thr_buf_args *bufp = (thr_buf_args *) arg;
00841     int     ret;
00842     u_char *addr;
00843     uint_t  size;
00844     int     index;
00845     EdtDev *edt_p;
00846     extern int errno;
00847 
00848     edt_p = bufp->edt_p;
00849     index = bufp->index;
00850     addr = edt_p->ring_buffers[index];
00851     size = edt_p->rb_control[index].size;
00852 
00853     /*
00854     * Start a read which will block forever in this thread. aioread() does
00855     * the same thing but won't allow as much concurrency.  Lseek orders the
00856     * buffers inside the driver. also aioread has exit problems
00857     */
00858     edt_msg(EDTDEBUG, "start %s for %d addr %x\n",
00859         bufp->writeflag ? "write" : "read", index, (u_int) addr);
00860     edt_set_errno(0);;
00861     if (bufp->writeflag)
00862         ret = pwrite(edt_p->fd, addr, size, index * 512);
00863     else
00864         ret = pread(edt_p->fd, addr, size, index * 512);
00865     if (ret == -1)
00866     {
00867         char    errstr[128];
00868 
00869         if (errno)
00870             perror("pread");
00871         sprintf(errstr, "aio buffer %d at 0x%x", index, (u_int) addr);
00872         edt_msg_perror(EDTDEBUG, errstr);
00873         edt_msg_perror(EDTDEBUG, "aiothread\n");
00874     }
00875     edt_msg(EDTDEBUG, "end aiothread for %d\n", index);
00876     return (0);
00877 }
00878 
00879 #endif
00880 
00888 int
00889 edt_use_umem_lock(EdtDev *edt_p, u_int use_lock)
00890 {
00891     int ret = 0 ;
00892     if (edt_p->ring_buffers_configured)
00893     {
00894         printf("Can't change umem lock method when ring buffers active\n") ;
00895         return(1) ;
00896     }
00897     edt_msg(EDTDEBUG, "use umem lock %d ",use_lock) ;
00898     ret = edt_ioctl(edt_p, EDTS_UMEM_LOCK, &use_lock) ;
00899     edt_msg(EDTDEBUG, "returns %d\n",ret) ;
00900     if (ret)
00901     {
00902         edt_msg(EDTDEBUG,
00903             "Can't use Umem lock expect on solaris 2.8 or above\n") ;
00904     }
00905     else
00906     {
00907         edt_msg(EDTDEBUG,"Setting umem lock\n") ;
00908     }
00909     return(ret) ;
00910 }
00911 
00912 int
00913 edt_get_umem_lock(EdtDev *edt_p)
00914 {
00915     u_int using_lock ;
00916     edt_ioctl(edt_p, EDTG_UMEM_LOCK, &using_lock) ;
00917     edt_msg(EDTDEBUG,"Using lock returns %d\n",using_lock) ;
00918     return(using_lock) ;
00919 }
00920 
00931 int
00932 edt_get_numbufs(EdtDev *edt_p)
00933 
00934 {
00935     int nb = 0;
00936     edt_ioctl(edt_p, EDTG_NUMBUFS, &nb);
00937     return nb;
00938 }
00939 
00940 /*
00941 * edt_configure_ring_buffer
00942 *
00943 * configures PCI Bus Configurable DMA Interface ring buffers
00944 *
00945 * @param edt_p: device handle returned from edt_open
00946 *      bufsize: size of each buffer
00947 *        nbufs: number of buffers
00948 *   data_direction:     indicates whether this connection is to
00949 *                      be used for output or input
00950 *     bufarray: array of pointers to application-allocated buffers
00951 *
00952 * @return 0 on success; -1 on error
00953 */
00954 
00955 static int
00956 edt_configure_ring_buffer(EdtDev * edt_p,
00957                           int index,
00958                           int bufsize,
00959                           int write_flag,
00960                           unsigned char *pdata)
00961 
00962 {
00963     buf_args sysargs;
00964     int allocated_size = bufsize;
00965     EdtRingBuffer *pring;
00966     int rc;
00967 
00968     if (index < 0 || index >= MAX_DMA_BUFFERS)
00969     {
00970         edt_set_errno(EINVAL); 
00971 
00972         fprintf(stderr,
00973             "invalid buffer index %d < 0 or >= MAX_DMA_BUFFERS (%d)\n",
00974             index, MAX_DMA_BUFFERS);
00975         return -1;
00976     }
00977 
00978     pring = &edt_p->rb_control[index];
00979 
00980 
00981 
00982     pring->size = bufsize;
00983     pring->write_flag = write_flag;
00984 
00985     if (pdata || (edt_p->mmap_buffers))
00986     {
00987         pring->owned = FALSE;
00988     }
00989     else
00990     {
00991 #ifdef _NT_
00992         /* round up to full page for fast file access */
00993         if (allocated_size & (SECTOR_SIZE-1))
00994             allocated_size = ((allocated_size / SECTOR_SIZE)+1)* SECTOR_SIZE;
00995 #endif
00996         pdata =
00997             edt_alloc(allocated_size);
00998         pring->owned = TRUE;
00999     }
01000 
01001     pring->allocated_size = allocated_size;
01002 
01003     edt_p->ring_buffers[index] = pdata;
01004 
01005     sysargs.index = index;
01006     sysargs.writeflag = write_flag;
01007 #ifdef WIN32
01008     sysargs.addr = (uint64_t) (pdata);
01009 #else
01010     sysargs.addr = (uint64_t) ((unsigned long)pdata);
01011 #endif
01012 
01013     sysargs.size = bufsize;
01014 #ifdef __hpux
01015     bzero(sysargs.addr,sysargs.size) ;
01016 #endif
01017 
01018     if (edt_p->mmap_buffers)
01019     {
01020         if ((rc = edt_ioctl(edt_p, EDTS_BUF_MMAP, &sysargs)) == 0)
01021         {
01022 #ifdef __sun
01023             int  using_lock = 0 ;
01024             int     count;
01025             thr_buf_args bufargs;
01026 
01027             using_lock = edt_get_umem_lock(edt_p) ;
01028 
01029             if (!using_lock)
01030             {
01031                 bufargs.edt_p = edt_p;
01032                 bufargs.index = index;
01033                 bufargs.writeflag = write_flag;
01034 
01035                 edt_msg(EDTDEBUG, "%d buffer thread\n", index);
01036                 if (thr_create(NULL, 0,
01037                     aio_thread,
01038                     (void *) &bufargs, THR_BOUND,
01039                     &pring->ring_tid))
01040                 {
01041                     edt_msg_perror(EDTWARN, "thr_create");
01042                 }
01043             }
01044             count = index + 1;
01045 
01046             edt_msg(EDTDEBUG, "Before WAITN");
01047             edt_ioctl(edt_p, EDTS_WAITN, &count);
01048             edt_msg(EDTDEBUG, "After WAITN");
01049 #endif
01050             return 0;
01051 
01052         }       
01053         else
01054         {
01055             edt_msg(EDT_MSG_FATAL, "Unable to configure ring buffer\n");
01056             edt_msg(EDT_MSG_FATAL, "rc = %d\n", rc);
01057             return rc;
01058         }
01059     } 
01060     else if (edt_ioctl(edt_p, EDTS_BUF, &sysargs) == 0)
01061     {
01062 #ifdef __sun
01063         int  using_lock = 0 ;
01064         int     count;
01065         thr_buf_args bufargs;
01066 
01067         using_lock = edt_get_umem_lock(edt_p) ;
01068 
01069         if (!using_lock)
01070         {
01071             bufargs.edt_p = edt_p;
01072             bufargs.index = index;
01073             bufargs.writeflag = write_flag;
01074 
01075             edt_msg(EDTDEBUG, "%d buffer thread\n", index);
01076             if (thr_create(NULL, 0,
01077                 aio_thread,
01078                 (void *) &bufargs, THR_BOUND,
01079                 &pring->ring_tid))
01080             {
01081                 edt_msg_perror(EDTWARN, "thr_create");
01082             }
01083             count = index + 1;
01084 
01085             edt_msg(EDTDEBUG, "Before WAITN");
01086             edt_ioctl(edt_p, EDTS_WAITN, &count);
01087             edt_msg(EDTDEBUG, "After WAITN");
01088         }
01089 #endif
01090         return 0;
01091     }
01092     return (-1);
01093 }
01094 
01095 /*
01096 * Obsolete - was used as a workaround for edt_set_direction().
01097 * Still used in legacy code, so keep for compatibility.
01098 * TODO: needs to be made compatible with edt_p->mmap_buffers.
01099 */
01100 int
01101 edt_add_ring_buffer(EdtDev * edt_p,
01102                     unsigned int bufsize,
01103                     int write_flag,
01104                     void *pdata)
01105 {
01106 
01107     int     index = -1;
01108 
01109     int     i;
01110 
01111     if (!edt_p->mmap_buffers)
01112     {
01113 
01114         /* allocate a slot for the data */
01115 
01116         for (i = 0; i < MAX_DMA_BUFFERS; i++)
01117             if (edt_p->ring_buffers[i] == NULL)
01118                 break;
01119 
01120         if (i == MAX_DMA_BUFFERS)
01121             return -1;
01122 
01123         index = i;
01124 
01125         edt_p->ring_buffer_numbufs++;
01126 
01127         edt_ioctl(edt_p, EDTS_NUMBUFS, &edt_p->ring_buffer_numbufs);
01128 
01129         edt_configure_ring_buffer(edt_p, index, bufsize, write_flag, pdata);
01130     }
01131 
01132     return index;
01133 }
01134 
01135 
01136 /*
01137 * Obsolete - was used as a workaround for edt_set_direction(), but
01138 * no longer needed.  Still may show up in customer code, so keep.
01139 * 
01140 * @return 0 on success, -1 on failure
01141 */
01142 int
01143 edt_configure_channel_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01144                                    int write_flag, unsigned char **bufarray)
01145 {
01146     return edt_configure_ring_buffers(edt_p, bufsize, numbufs,
01147         write_flag, bufarray) ;
01148 }
01149 
01150 static
01151 int edt_check_ring_buf_parms(EdtDev *edt_p, int numbufs, int bufsize, 
01152                              unsigned char *pdata, unsigned char ** bufarray)
01153 
01154 {
01155 
01156     int maxbufs;
01157 
01158     if (!edt_p)
01159     {
01160         edt_msg_perror(EDTFATAL, "Invalid edt handle\n");
01161         return -1;
01162     }
01163 
01164 
01165     /* Odd number of bytes is illegal.  Mark & Chet Oct'2000 */
01166     if (bufsize & 0x01)
01167     {
01168         edt_set_errno(EINVAL); ;
01169 
01170         edt_msg_perror(EDTFATAL, "edt_configure_ring_buffers: bufsize must be an even number of bytes\n") ;
01171         return -1 ;
01172     }
01173     maxbufs = edt_get_max_buffers(edt_p) ;
01174     if (numbufs > maxbufs)
01175     {
01176 
01177         edt_set_errno(EINVAL); ;
01178 
01179         edt_msg_perror(EDTFATAL, 
01180             "edt_configure_ring_buffers: number of bufs exceeds maximum\n") ;
01181         edt_msg_perror(EDTFATAL, 
01182             "use edt_set_max_buffers to increase max\n") ;
01183         return -1 ;
01184     }   
01185 
01186     edt_p->mmap_buffers = edt_get_mmap_buffers(edt_p);
01187 
01188     if (edt_p->mmap_buffers)
01189     {
01190         if (edt_p->buffer_granularity < PAGE_SIZE)
01191             edt_p->buffer_granularity = PAGE_SIZE;
01192 
01193     }
01194 
01195     if (edt_p->mmap_buffers && ((pdata != NULL) || (bufarray != NULL)))
01196     {
01197 
01198         edt_set_errno(EINVAL); ;
01199 
01200         edt_msg_perror(EDTFATAL, 
01201             "edt_configure_ring_buffers: can't pass in user pointer when using mmap kernel buffers\n") ;
01202 
01203         return -1;
01204     }
01205 
01206     return 0;
01207 }
01208 
01209 #define EDT_DMAMEM_OFFSET 0x10000000
01210 
01211 int
01212 edt_unmap_dmamem(EdtDev *edt_p)
01213 {
01214 
01215 #ifdef __linux__
01216 
01217     if (edt_p->base_buffer)
01218         munmap(edt_p->base_buffer, edt_p->totalsize);
01219 
01220 #endif
01221 
01222     return 0;
01223 }
01224 
01225 caddr_t
01226 edt_map_dmamem(EdtDev *edt_p)
01227 {
01228 
01229     caddr_t     ret = NULL;
01230     int pagen = EDT_DMAMEM_OFFSET;
01231 
01232 
01233 #ifdef __linux__
01234 
01235     ret = (caddr_t) mmap((caddr_t)0, edt_p->totalsize, PROT_READ|PROT_WRITE,
01236         MAP_SHARED, edt_p->fd, pagen);
01237 #endif
01238 
01239 
01240     if (ret == ((caddr_t)-1)) {
01241         perror("mmap call");
01242         return(0) ;
01243     }   
01244 
01245     return(ret) ;
01246 }
01247 
01248 static int
01249 edt_allocate_ring_buffer_memory(EdtDev *edt_p, int bufsize, int numbufs, u_char *user_mem, u_char **buffers)
01250 
01251 {
01252 
01253     unsigned char * bp;
01254     int i;
01255 
01256     edt_p->fullbufsize = edt_get_total_bufsize(edt_p, bufsize, edt_p->header_size);
01257 
01258     edt_p->totalsize = edt_p->fullbufsize * numbufs;
01259 
01260     if (edt_p->mmap_buffers)
01261     {
01262         /* don't allocate, we'll do that later */
01263         for (i=0;i<numbufs;i++)
01264             buffers[i] = NULL;
01265 
01266         return 0;
01267     }
01268 
01269     if (edt_p->base_buffer)
01270     {
01271         edt_free(edt_p->base_buffer);
01272         edt_p->base_buffer = NULL;
01273     }
01274 
01275     if (user_mem)
01276     {
01277         bp = user_mem;
01278     }
01279     else
01280     {
01281 
01282 
01283         edt_p->ring_buffers_allocated = TRUE;
01284         edt_p->base_buffer = edt_alloc(edt_p->totalsize);
01285 
01286         if (!edt_p->base_buffer)
01287         {
01288             edt_msg_perror(EDTFATAL, "Unable to allocate buffer memory\n");
01289             return -1;
01290         }
01291 
01292         bp = edt_p->base_buffer;
01293 
01294 
01295     }
01296 
01297     if (edt_p->header_size < 0)
01298         bp += -((int) edt_p->header_size);
01299 
01300     for (i=0;i<numbufs;i++)
01301     {
01302         buffers[i] = bp;
01303         bp += edt_p->fullbufsize;
01304     }
01305 
01306 
01307     return 0;
01308 
01309 }
01310 
01311 
01312 static int
01313 edt_setup_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01314                        int write_flag, unsigned char *pdata, unsigned char **bufarray)
01315 {
01316     int     i;
01317     int rc;
01318 
01319     u_char *localbuf[MAX_DMA_BUFFERS];
01320     u_char ** buffers;
01321 
01322     buffers = (bufarray != NULL)?bufarray:localbuf;
01323 
01324     if ((rc = edt_check_ring_buf_parms(edt_p, numbufs, bufsize,  pdata, bufarray)) != 0)
01325         return rc;
01326 
01327     if (edt_p->ring_buffers_configured)
01328         edt_disable_ring_buffers(edt_p);
01329 
01330     edt_p->nextwbuf = 0;
01331     edt_p->donecount = 0;
01332     edt_p->ring_buffer_bufsize = bufsize;
01333     edt_p->ring_buffer_numbufs = numbufs;
01334 
01335     if (write_flag)
01336         edt_set_direction(edt_p, EDT_WRITE);
01337     else
01338         edt_set_direction(edt_p, EDT_READ);
01339 
01340     edt_p->write_flag = write_flag;
01341 
01342     edt_ioctl(edt_p, EDTS_NUMBUFS, &numbufs);
01343 
01344     if (bufarray == NULL)
01345     {
01346         edt_allocate_ring_buffer_memory(edt_p, bufsize, numbufs, pdata, buffers);
01347 
01348         edt_p->ring_buffers_allocated = !edt_p->mmap_buffers && (pdata == NULL);
01349     }
01350 
01351     for (i = 0; i < numbufs; i++)
01352     {
01353         if (edt_configure_ring_buffer(edt_p, i,
01354             bufsize,
01355             write_flag,
01356             buffers[i]) == 0)
01357         {
01358 
01359         }
01360         else
01361         {
01362             return -1;
01363         }
01364 
01365 #ifdef __hpux
01366         edt_dmasync_fordev(edt_p, i, 0, 0) ;
01367 #endif
01368 
01369     }
01370 
01371 
01372 #if defined(__hpux)
01373     {
01374         int pret ;
01375         /* pret = plock(DATLOCK) ;*/
01376         pret = plock(PROCSHLIBLOCK) ;
01377     }
01378 #elif defined(sgi)
01379     mlockall(MCL_FUTURE); 
01380 #endif
01381 
01382     if (edt_p->mmap_buffers)
01383     {
01384         u_char *bp;
01385 
01386         edt_p->base_buffer = (u_char *) edt_map_dmamem(edt_p);
01387         bp = edt_p->base_buffer;
01388 
01389         for (i=0;i<numbufs;i++)
01390         {
01391             edt_p->ring_buffers[i] = bp;
01392             bp += edt_p->fullbufsize;
01393         }
01394 
01395         /* go ahead and page it in */
01396         bp = edt_p->base_buffer;
01397         for (i=0; i<(int)edt_p->totalsize;i += PAGE_SIZE)
01398             bp[i] = 0x5a;
01399 
01400 
01401     }
01402 
01403     edt_p->ring_buffers_configured = 1;
01404 
01405     return 0;
01406 }
01407 
01408 
01409 
01410 void edt_set_buffer_granularity(EdtDev *edt_p, u_int granularity)
01411 
01412 {
01413     edt_p->buffer_granularity = granularity;
01414 }
01415 
01416 
01427 int
01428 edt_get_total_bufsize(EdtDev *edt_p,
01429                       int bufsize, 
01430                       int header_size)
01431 
01432 {
01433     int fullbufsize;
01434 
01435     fullbufsize = header_size + bufsize;
01436 
01437     if (edt_p->buffer_granularity)
01438         if (fullbufsize % edt_p->buffer_granularity)
01439             fullbufsize = ((fullbufsize / edt_p->buffer_granularity)+1)* edt_p->buffer_granularity;     
01440 
01441     return fullbufsize;
01442 }
01443 
01444 
01483 int
01484 edt_configure_ring_buffers(EdtDev *edt_p, int bufsize, int numbufs,
01485                            int write_flag, unsigned char **bufarray)
01486 {
01487     return edt_setup_ring_buffers(edt_p, bufsize, numbufs, write_flag, NULL, bufarray);
01488 
01489 }
01490 
01501 int
01502 edt_configure_block_buffers_mem(EdtDev *edt_p, 
01503                                 int bufsize, 
01504                                 int numbufs, 
01505                                 int write_flag,
01506                                 int header_size, 
01507                                 int header_before,
01508                                 u_char *user_mem)
01509 
01510 {
01511 
01512     /* check for valid arguments */
01513     if (header_before && header_size)
01514     {   
01515         if (header_size & (SECTOR_SIZE-1))
01516             header_size = ((header_size / SECTOR_SIZE)+1)* SECTOR_SIZE; 
01517     }
01518 
01519 
01520     edt_p->header_size = header_size;
01521     edt_p->header_offset = (header_before)? -header_size : bufsize;
01522 
01523 
01524     return edt_setup_ring_buffers(edt_p, bufsize, numbufs, write_flag, user_mem, NULL);
01525 
01526 }
01527 
01528 
01563 int
01564 edt_configure_block_buffers(EdtDev *edt_p, int bufsize, int numbufs, int write_flag,
01565                             int header_size, int header_before)
01566 
01567 {
01568 
01569     return edt_configure_block_buffers_mem(edt_p,
01570         bufsize,
01571         numbufs,
01572         write_flag,
01573         header_size,
01574         header_before,
01575         NULL);
01576 
01577 }
01578 
01579 
01593 int
01594 edt_disable_ring_buffer(EdtDev *edt_p, 
01595                         int whichone)
01596 
01597 {
01598     if (edt_p->ring_buffers[whichone])
01599     {
01600         /* detach buffer from DMA resources */
01601 
01602         edt_ioctl(edt_p, EDTS_FREEBUF, &whichone);
01603         edt_msg(EDTDEBUG, "free buf %d\n", whichone);
01604 
01605 #ifdef __sun
01606         {
01607             u_int using_lock ;
01608             using_lock = edt_get_umem_lock(edt_p) ;
01609             if (!using_lock)
01610             {
01611                 edt_msg(EDTDEBUG, "joining user buf %d tid %x\n", 
01612                     whichone, edt_p->rb_control[whichone].ring_tid);
01613                 thr_join(edt_p->rb_control[whichone].ring_tid, NULL, NULL);
01614 
01615                 edt_msg(EDTDEBUG, "join user buf %d done\n", whichone);
01616             }
01617         }
01618 #endif
01619         /* free data pointer if we own it */
01620         if (edt_p->rb_control[whichone].owned)
01621         {
01622             edt_msg(EDTDEBUG, "free user buf %d\n", whichone);
01623             edt_free(edt_p->ring_buffers[whichone]);
01624         }
01625 
01626         edt_p->ring_buffers[whichone] = NULL;
01627 
01628     }
01629 #if defined(__hpux)
01630     {
01631         int pret ;
01632         pret = plock(UNLOCK) ;
01633     }
01634 #endif
01635 
01636     return 0;
01637 
01638 }
01639 
01640 
01652 int
01653 edt_disable_ring_buffers(EdtDev *edt_p)
01654 
01655 {
01656     int   i;
01657 
01658     /* for (i = 0; i < edt_p->ring_buffer_numbufs; i++)*/
01659     for (i = edt_p->ring_buffer_numbufs - 1; i >= 0 ; i--)
01660     {
01661         edt_disable_ring_buffer(edt_p,i);
01662     }
01663 
01664     edt_p->ring_buffers_configured = 0;
01665     edt_p->ring_buffers_allocated = 0;
01666 #if defined(__hpux)
01667     {
01668         int pret ;
01669         pret = plock(UNLOCK) ;
01670     }
01671 #elif defined(sgi)
01672     munlockall();
01673 #endif
01674 
01675     if (edt_p->base_buffer )
01676     {
01677 
01678         if (edt_p->mmap_buffers)
01679             edt_unmap_dmamem(edt_p);
01680         else
01681             edt_free(edt_p->base_buffer);
01682         edt_p->base_buffer = NULL;
01683     }
01684     /* Steve 1/11/01 to fix pdv_setsize bug */
01685     /* added NUMBUFS to fix dmaid issue 2/19/03 */
01686     {
01687         int one = 1;
01688         edt_p->ring_buffer_numbufs = 0;
01689         edt_ioctl(edt_p, EDTS_NUMBUFS, &one);
01690         edt_ioctl(edt_p, EDTS_CLEAR_DMAID, &one);
01691     }
01692 
01693     return 0;
01694 }
01695 
01710 int
01711 edt_start_buffers(EdtDev *edt_p, uint_t count)
01712 {
01713     if (edt_p->devid == DMY_ID && edt_p->dd_p)
01714         dmy_started += count ;
01715     edt_msg(EDTDEBUG, "edt_start_buffers %d\n", count);
01716     edt_ioctl(edt_p, EDTS_STARTBUF, &count);
01717     return 0;
01718 }
01719 
01720 
01721 int
01722 edt_lockoff(EdtDev * edt_p)
01723 {
01724     int     count = 0;
01725 
01726     edt_ioctl(edt_p, EDTS_STARTBUF, &count);
01727     return 0;
01728 }
01729 
01739 unsigned int
01740 edt_allocated_size(EdtDev *edt_p, int buffer)
01741 
01742 {
01743     if (buffer >= 0 && buffer < (int) edt_p->ring_buffer_numbufs)
01744     {
01745         return edt_p->rb_control[buffer].allocated_size;
01746     }
01747     return 0;
01748 }
01749 
01771 int
01772 edt_set_buffer(EdtDev *edt_p, uint_t bufnum)
01773 {
01774     edt_ioctl(edt_p, EDTS_SETBUF, &bufnum);
01775     edt_p->donecount = bufnum;
01776     if (edt_p->ring_buffer_numbufs)
01777         edt_p->nextwbuf = bufnum % edt_p->ring_buffer_numbufs;
01778     return 0;
01779 }
01780 
01801 int
01802 edt_read(EdtDev *edt_p, 
01803          void   *buf, 
01804          uint_t  size)
01805 {
01806     int     retval;
01807 
01808 #ifdef USB
01809     if (edt_p->devtype == USB_ID)
01810     {
01811         if (usb_claim_interface(edt_p->usb_p, 0) < 0)
01812         {
01813             edt_set_errno(EBUSY); ;
01814             return -1 ;
01815         }
01816 
01817         retval = usb_bulk_read(edt_p->usb_p, edt_p->usb_bulk_read_endpoint,
01818             buf, size, edt_p->usb_rtimeout);
01819 
01820         usb_release_interface(edt_p->usb_p, 0);
01821     }
01822     else
01823 #endif /* USB */
01824     {
01825 
01826 #ifdef _NT_
01827         uint_t  Length;
01828 #endif
01829 
01830         if (size & 0x01) /* Odd no of bytes illegal.  Mark & Chet Oct'2000 */
01831             -- size ;
01832 
01833         if (edt_p->last_direction != 1)
01834             edt_set_direction(edt_p, EDT_READ);
01835 #ifdef _NT_
01836         if ((retval = ReadFile(edt_p->fd, buf, size, &Length, NULL)) == 0)
01837             edt_msg_perror(EDTFATAL, "edt_read:ReadFile");
01838         retval = Length;
01839 #else
01840 #if defined(__APPLE__)
01841         if (edt_p->devid != DMY_ID)
01842         {
01843             int retval ;
01844             unsigned char *bufarray[1] ;
01845             bufarray[0] = buf ;
01846             retval = edt_configure_ring_buffers(edt_p, size, 1, EDT_READ, bufarray) ;
01847             if (retval) return retval;
01848 
01849             edt_start_buffers(edt_p, 1) ;
01850             retval = edt_wait_for_buffers(edt_p, 1) ;
01851             if (retval < 0)
01852             {
01853                 size = edt_get_timeout_count(edt_p);
01854                 edt_msg(EDTDEBUG, "edt_read timeout with count %d\n", retval);
01855             }
01856             edt_disable_ring_buffers(edt_p) ;
01857             return(size) ;
01858         }
01859 #endif
01860         edt_p->b_count += size ;
01861         if (edt_p->b_count > 0x40000000) /* 1GB */
01862         {
01863             lseek(edt_p->fd, 0, 0) ;
01864             edt_p->b_count = 0 ;
01865         }
01866         if ((retval = read(edt_p->fd, buf, size)) < 0)
01867         {
01868 #if defined(__sun) || defined(__linux__)
01869             if (errno == ETIMEDOUT)
01870             {
01871                 retval = edt_get_timeout_count(edt_p);
01872                 edt_msg(EDTDEBUG, "edt_read timeout with count %d\n", retval);
01873             }
01874             else
01875 #endif
01876                 edt_msg_perror(EDTDEBUG, "edt_read:Read");
01877         }
01878 #endif
01879     }
01880     return (retval);
01881 }
01882 
01906 int
01907 edt_write(EdtDev *edt_p,
01908           void   *buf,
01909           uint_t  size)
01910 
01911 {
01912     uint_t  Length = 0;
01913 
01914 #ifdef USB
01915     if (edt_p->devtype == USB_ID)
01916     {
01917         if (usb_claim_interface(edt_p->usb_p, 0) < 0)
01918         {
01919             edt_set_errno(EBUSY); ;
01920             return -1 ;
01921         }
01922 
01923         Length = usb_bulk_write(edt_p->usb_p, edt_p->usb_bulk_write_endpoint,
01924             buf, size, edt_p->usb_wtimeout);
01925 
01926         usb_release_interface(edt_p->usb_p, 0);
01927     }
01928     else
01929 #endif /* USB */
01930     {
01931 
01932         if (size & 0x01) /* Odd no of bytes illegal.  Mark & Chet Oct'2000 */
01933             -- size ;
01934 
01935         if (edt_p->last_direction != (EDT_WRITE+1))
01936             edt_set_direction(edt_p, EDT_WRITE);
01937 #ifdef _NT_
01938         if (!WriteFile(edt_p->fd, buf, size, &Length, NULL))
01939             edt_msg_perror(EDTWARN, "WRITEFile");
01940 #else
01941 #if defined(__APPLE__)
01942         if (edt_p->devid != DMY_ID)
01943         {
01944             int retval ;
01945             unsigned char *bufarray[1] ;
01946             bufarray[0] = buf ;
01947             retval = edt_configure_ring_buffers(edt_p, size, 1, EDT_WRITE, bufarray) ;
01948             edt_start_buffers(edt_p, 1) ;
01949             /* edt_wait_for_buffers(edt_p, 1) ; */
01950             return(size) ;
01951         }
01952 #endif
01953         edt_p->b_count += size ;
01954         if (edt_p->b_count > 0x40000000) /* 1GB */
01955         {
01956             lseek(edt_p->fd, 0, 0) ;
01957             edt_p->b_count = 0 ;
01958         }
01959         if (write(edt_p->fd, buf, size) < 0)
01960         {
01961             edt_msg_perror(EDTDEBUG, "write");
01962             Length = -1;
01963         }
01964         else
01965             Length = size;
01966 #endif
01967     }
01968 
01969     return (Length);
01970 }
01971 
01972 int
01973 edt_write_pio(EdtDev *edt_p, u_char *buf, int size)
01974 
01975 {
01976     edt_sized_buffer argbuf;
01977 
01978     argbuf.size = size;
01979 
01980     memcpy(argbuf.data, buf, size);
01981 
01982     return edt_ioctl(edt_p, EDTS_WRITE_PIO, &argbuf);
01983 
01984 }
01985 
01986 #define CLKSAFTER 32
01987 
01988 void
01989 edt_prog_write(EdtDev *edt_p, u_int val)
01990 
01991 {
01992 
01993     edt_reg_write(edt_p, EDT_DMA_CFG, val);
01994 }
01995 
01996 int
01997 edt_prog_read(EdtDev *edt_p)
01998 
01999 {
02000     return (edt_reg_read(edt_p, EDT_DMA_CFG));
02001 
02002 }
02003 
02013 int
02014 edt_program_xilinx(EdtDev *edt_p, const u_char *buf, int size, int do_sleep)
02015 {
02016     int base, xfer, ret;
02017 
02018     if ((ret = edt_program_xilinx_start(edt_p)) != 0)
02019         return ret;
02020 
02021     for (base=0;base < size; base += SIZED_DATASIZE)
02022     {
02023         if (size - base > SIZED_DATASIZE)
02024             xfer = SIZED_DATASIZE;
02025         else xfer = size - base;
02026         edt_program_xilinx_chunk(edt_p, buf+base, xfer, do_sleep);
02027     }
02028 
02029     return edt_program_xilinx_end(edt_p);
02030 }
02031 
02037 int
02038 edt_program_xilinx_start(EdtDev *edt_p)
02039 {
02040     int loop = 0;
02041     int regrd;
02042 
02043     /* wait for done to be low */
02044     edt_prog_write(edt_p, 0);
02045 
02046     edt_msg(EDTDEBUG, "\nedt_program_xilinx_start: waiting for DONE low\n");
02047 
02048     while ((regrd = edt_prog_read(edt_p)) & X_DONE)
02049     {
02050         if (loop++ > 10000000)
02051         {
02052             /* edt_msg(EDTDEBUG, "edt_program_xilinx_start: reading %08x waiting for not DONE %08x\n",
02053             regrd, X_DONE); */
02054             return (1);
02055         }
02056     }
02057     edt_msg(EDTDEBUG, "loop %d\n", loop);
02058     /* set PROG and INIT high */
02059     edt_prog_write(edt_p, X_PROG | X_INIT);
02060 
02061     /* wait for INITSTAT to go high */
02062     edt_msg(EDTDEBUG, "waiting for INIT high\n");
02063     loop = 0;
02064     while (((regrd = edt_prog_read(edt_p)) & X_INITSTAT) == 0)
02065     {
02066         /* edt_msg(EDTDEBUG, "reading %08x waiting for not INIT %08x\n", regrd, X_INITSTAT); */
02067         if (loop++ > 1000000)
02068         {
02069             /* edt_msg(EDTDEBUG, "reading %08x waiting for not INIT %08x\n", regrd, X_INITSTAT); */
02070             return (1);
02071         }
02072     }
02073     edt_ref_tmstamp(edt_p, 0x11130000);
02074     edt_msg(EDTDEBUG, "loop %d\n", loop);
02075 
02076     return 0;
02077 }
02078 
02091 void
02092 edt_program_xilinx_chunk(EdtDev *edt_p, const u_char *buf, int xfer, int do_sleep)
02093 {
02094 
02095     edt_sized_buffer argbuf;
02096 
02097     memcpy(argbuf.data, buf, xfer);
02098     argbuf.size = xfer;
02099 
02100     edt_ioctl(edt_p, EDTS_PROG_XILINX, &argbuf);
02101     if (do_sleep)
02102         edt_msleep(0);
02103 }
02104 
02110 int
02111 edt_program_xilinx_end(EdtDev *edt_p)
02112 {
02113     int bad_program = 0;
02114     int loop = 0;
02115     int regrd;
02116 
02117     edt_msg(EDTDEBUG, "edt_program_xilinx_end: waiting for DONE high\n");
02118 
02119     edt_ref_tmstamp(edt_p, 0x11140000);
02120 
02121     edt_msg(EDTDEBUG, "edt_program_xilinx_end: prog_read %x DONE %x\n", edt_prog_read(edt_p), X_DONE);
02122 
02123 
02124     while ((((regrd = edt_prog_read(edt_p)) & X_DONE) == 0) && !bad_program)
02125     {
02126         edt_prog_write(edt_p, X_DATA | X_CCLK | X_INIT | X_PROG);
02127         if (loop > CLKSAFTER)
02128         {
02129             edt_msg(EDTDEBUG, "> %d writes without done - fail\n", CLKSAFTER);
02130             bad_program = 1;
02131         }
02132         loop++;
02133     }
02134 
02135     return (bad_program);
02136 
02137 }
02138 
02139 
02140 
02152 unsigned char *
02153 edt_next_writebuf(   EdtDev *edt_p)
02154 
02155 {
02156     unsigned char *buf_p;
02157 
02158     buf_p = edt_p->ring_buffers[edt_p->nextwbuf];
02159     edt_p->nextwbuf = ++edt_p->nextwbuf % edt_p->ring_buffer_numbufs;
02160     return buf_p;
02161 }
02162 
02175 unsigned char **
02176 edt_buffer_addresses(EdtDev *edt_p)
02177 {
02178     return (edt_p->ring_buffers);
02179 }
02180 
02203 unsigned char *
02204 edt_wait_buffers_timed(EdtDev * edt_p, int count, u_int * timep)
02205 {
02206     u_char *ret;
02207 
02208     edt_msg(EDTDEBUG, "edt_wait_buffers_timed()\n");
02209 
02210     ret = edt_wait_for_buffers(edt_p, count);
02211     edt_get_timestamp(edt_p, timep, edt_p->donecount - 1);
02212 
02213     edt_msg(EDTDEBUG, "buf %d done %s (%x %x)\n",
02214         edt_p->donecount,
02215         edt_timestring(timep),
02216         timep[0], timep[1]);
02217 
02218     return (ret);
02219 }
02220 
02234 unsigned char *
02235 edt_last_buffer(EdtDev * edt_p)
02236 {
02237     u_char *ret;
02238     bufcnt_t     donecount;
02239     bufcnt_t     last_wait;
02240     int     delta;
02241 
02242     donecount = edt_done_count(edt_p);
02243     last_wait = edt_p->donecount;
02244 
02245     edt_msg(EDTDEBUG, "edt_last_buffer() last %d cur %d\n",
02246         last_wait, donecount);
02247 
02248     delta = donecount - last_wait;
02249 
02250     if (delta == 0)
02251         delta = 1;
02252 
02253     ret = edt_wait_for_buffers(edt_p, delta) ;
02254     return (ret);
02255 }
02256 
02278 unsigned char *
02279 edt_last_buffer_timed(EdtDev * edt_p, u_int * timep)
02280 {
02281     u_char *ret;
02282     bufcnt_t     donecount;
02283     bufcnt_t     last_wait;
02284     int     delta;
02285 
02286     donecount = edt_done_count(edt_p);
02287     last_wait = edt_p->donecount;
02288 
02289     edt_msg(EDTDEBUG, "edt_last_buffer_timed() last %d cur %d\n",
02290         last_wait, donecount);
02291 
02292     delta = donecount - last_wait;
02293 
02294     if (delta == 0)
02295         delta = 1;
02296 
02297     ret = edt_wait_buffers_timed(edt_p, delta, timep);
02298     return (ret);
02299 }
02300 
02301 char   *
02302 edt_timestring(u_int * timep)
02303 {
02304     static char timestr[100];
02305     struct tm *tm_p;
02306     time_t testtm ;
02307 
02308     /* timep is sec,nsec in two 32 bit ints */
02309     /* works when passed to localtime on 32 bit system, but not 64 */
02310     testtm = timep[0] ;
02311     tm_p = localtime(&testtm);
02312     timep++;
02313     sprintf(timestr, "%02d:%02d:%02d.%06d",
02314         tm_p->tm_hour,
02315         tm_p->tm_min,
02316         tm_p->tm_sec,
02317         *timep);
02318 
02319     return timestr;
02320 }
02321 
02339 int                        
02340 edt_do_timeout(EdtDev *edt_p)
02341 
02342 {
02343     int dummy;
02344 
02345     return edt_ioctl(edt_p,EDTS_DOTIMEOUT,&dummy);
02346 
02347 }
02348 
02377 unsigned char *
02378 edt_wait_for_buffers(EdtDev * edt_p, int count)
02379 {
02380     int     bufnum;
02381     int     ret = 0;
02382     bufcnt_t tmpcnt = count ;
02383 #ifdef _NT_
02384     int timeoutval = edt_get_rtimeout(edt_p);
02385 #endif
02386 
02387     edt_msg(EDTDEBUG, "edt_wait_for_buffers(%d)\n", count);
02388 
02389     if (edt_p->ring_buffer_numbufs == 0)
02390     {
02391         edt_msg(EDTDEBUG, "wait for buffers called with 0 buffers\n");
02392         return (0);
02393     }
02394     tmpcnt += edt_p->donecount;
02395 
02396 #ifdef _NT_
02397     if (edt_get_drivertype(edt_p) != EDT_WDM_DRIVER)
02398 
02399     {
02400         HANDLE event;
02401         int rc;
02402 
02403         if (!edt_p->event_funcs[EDT_EVENT_BUF].wait_event)
02404         {
02405             edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
02406         }
02407 
02408         event = edt_p->event_funcs[EDT_EVENT_BUF].wait_event;
02409 
02410         while (edt_done_count(edt_p) < tmpcnt)
02411         {
02412 
02413             /* wait for event */
02414 
02415             if (timeoutval == 0)
02416                 timeoutval = INFINITE;
02417 
02418             ret = EDT_WAIT_OK;
02419             edt_clear_wait_status(edt_p);
02420 
02421             rc = WaitForSingleObject(event, timeoutval);
02422 
02423             if (rc == WAIT_TIMEOUT)
02424             {
02425                 if (edt_get_timeout_ok(edt_p))
02426                 {
02427                     ret = EDT_WAIT_OK_TIMEOUT;
02428                 }
02429                 else
02430                 {
02431                     edt_msg(EDTDEBUG, "timeout...\n");
02432 
02433                     /* deal with timeout */
02434 
02435                     edt_do_timeout(edt_p);
02436                     ResetEvent(event) ;
02437                     ret = EDT_WAIT_TIMEOUT;
02438                 }
02439                 break;
02440             }
02441             else if (edt_had_user_dma_wakeup(edt_p))
02442             {
02443                 ret = EDT_WAIT_USER_WAKEUP;
02444 
02445             }
02446         }
02447     }
02448     else
02449     {
02450         ret = edt_ioctl(edt_p, EDTS_WAITBUF, &tmpcnt);
02451     }
02452 #else
02453 
02454     ret = edt_ioctl(edt_p, EDTS_WAITBUF, &tmpcnt);
02455 
02456 #endif
02457 
02458     ret = edt_get_wait_status(edt_p);
02459 
02460     edt_msg(EDTDEBUG, "edt_wait_for_buffers %d done ret = %d\n", count,
02461         ret);
02462     if (ret  == EDT_WAIT_OK || ret == EDT_WAIT_TIMEOUT)
02463         edt_p->donecount = tmpcnt;
02464 
02465     bufnum = (edt_p->donecount - 1) % edt_p->ring_buffer_numbufs;
02466 
02467 #ifdef VXWORKS
02468     /* TODO - move this to dma done */
02469     /* ATTN - not right - should be bytecount? */
02470     CACHE_DMA_INVALIDATE(edt_p->ring_buffers[bufnum],
02471         edt_p->rb_control[bufnum].size);
02472 #if defined(AV3_BOARD)
02473     printf("cache inv %x %x\n",
02474         edt_p->ring_buffers[bufnum], edt_p->rb_control[bufnum].size);
02475     bslPpcCacheInv(edt_p->ring_buffers[bufnum], edt_p->rb_control[bufnum].size);
02476 #endif
02477 #endif
02478 
02479     return (edt_p->ring_buffers[bufnum]);
02480 }
02481 
02506 int
02507 edt_get_timestamp(EdtDev * edt_p, u_int * timep, u_int bufnum)
02508 {
02509     /* we return sec and nsec - change to usec */
02510     u_int   timevals[3];
02511 
02512     timevals[0] = bufnum;
02513     if (edt_p->devid == DMY_ID)
02514     {
02515         u_int inttime ;
02516         double testtime ;
02517         timevals[0] = bufnum ;
02518         testtime = edt_timestamp();
02519         inttime = (u_int)testtime ;
02520         testtime -= inttime ;
02521         *timep++ = inttime ;
02522         *timep++ = (u_int)(testtime * 1000000.0) ;
02523     }
02524     else
02525     {
02526         edt_ioctl(edt_p, EDTG_TMSTAMP, timevals);
02527 
02528         edt_msg(EDTDEBUG, "%x %x %x %x ", bufnum,
02529             timevals[0],
02530             timevals[1],
02531             timevals[2]);
02532         *timep++ = timevals[1];
02533         *timep++ = timevals[2];
02534     }
02535 
02536     return (timevals[0]);
02537 }
02538 
02551 unsigned char *
02552 edt_wait_for_next_buffer(EdtDev *edt_p)
02553 
02554 {
02555     bufcnt_t count;
02556     unsigned int bufnum;
02557 #ifdef _NT_
02558     int timeoutval = edt_get_rtimeout(edt_p);
02559 #endif
02560 
02561     edt_ioctl(edt_p, EDTG_BUFDONE, &count);
02562     count++;
02563     if (edt_p->ring_buffer_numbufs == 0) {
02564         /* maybe they forgot edt_configure_ring_buffers */
02565         return NULL; 
02566     }
02567     bufnum = (count - 1) % edt_p->ring_buffer_numbufs;
02568 
02569 #ifdef _NT_
02570     if (edt_get_drivertype(edt_p) != EDT_WDM_DRIVER)
02571 
02572     {
02573         HANDLE event;
02574         int rc;
02575 
02576         if (!edt_p->event_funcs[EDT_EVENT_BUF].wait_event)
02577         {
02578             edt_get_kernel_event(edt_p, EDT_EVENT_BUF);
02579         }
02580 
02581         event = edt_p->event_funcs[EDT_EVENT_BUF].wait_event;
02582 
02583         while (edt_done_count(edt_p) < (bufcnt_t) count)
02584         {
02585 
02586             /* wait for event */
02587 
02588             if (timeoutval == 0)
02589                 timeoutval = INFINITE;
02590 
02591             rc = WaitForSingleObject(event, timeoutval);
02592 
02593             if (rc == WAIT_TIMEOUT)
02594             {
02595                 edt_msg(EDTDEBUG, "timeout...\n");
02596 
02597                 /* deal with timeout */
02598 
02599                 edt_do_timeout(edt_p);
02600                 ResetEvent(event) ;
02601 
02602                 break;
02603             }
02604 
02605         }
02606 
02607     }
02608     else
02609     {
02610         edt_ioctl(edt_p, EDTS_WAITBUF, &count);
02611     }
02612 #else
02613 
02614     edt_ioctl(edt_p, EDTS_WAITBUF, &count);
02615 
02616 #endif
02617 
02618     edt_msg(EDTDEBUG, "edt_wait_for_next_buffer %d done\n", count);
02619     edt_p->donecount = count;
02620     return (edt_p->ring_buffers[bufnum]);
02621 }
02622 
02623 
02638 unsigned char *
02639 edt_get_current_dma_buf(EdtDev * edt_p)
02640 {
02641     unsigned int count;
02642     unsigned int bufnum;
02643     unsigned int todo ;
02644     /* find out how many are done */
02645 
02646     edt_ioctl(edt_p, EDTG_BUFDONE, &count);
02647 
02648     todo = edt_get_todo(edt_p);
02649 
02650     /* if a dma is currently started
02651     * go to next buffer */
02652 
02653     if (todo == 0 || todo > count)
02654         count ++;
02655 
02656     bufnum = (count - 1) % edt_p->ring_buffer_numbufs;
02657 
02658     return (edt_p->ring_buffers[bufnum]);
02659 
02660 }
02661 
02682 unsigned char *
02683 edt_check_for_buffers(EdtDev *edt_p, uint_t count)
02684 {
02685     unsigned int driver_count;
02686     unsigned int bufnum;
02687     unsigned int target;
02688 
02689     target = count + edt_p->donecount;
02690     bufnum = (target - 1) % edt_p->ring_buffer_numbufs;
02691     edt_ioctl(edt_p, EDTG_BUFDONE, &driver_count);
02692     if (driver_count >= target)
02693     {
02694         return edt_wait_for_buffers(edt_p, count);
02695     }
02696     else
02697         return (NULL);
02698 }
02699 
02715 bufcnt_t
02716 edt_done_count(EdtDev * edt_p)
02717 {
02718     bufcnt_t  donecount = 0;
02719 
02720     if (edt_p->devid == DMY_ID)
02721     {
02722         if (edt_p->dd_p)
02723         {
02724             donecount = dmy_started;
02725         }
02726         else printf("DEBUG - dd_p not set for DMY_ID\n") ;
02727     }
02728     else
02729         edt_ioctl(edt_p, EDTG_BUFDONE, &donecount);
02730     return (donecount);
02731 }
02732 
02733 uint_t
02734 edt_overflow(EdtDev * edt_p)
02735 {
02736     uint_t  overflow;
02737 
02738     edt_ioctl(edt_p, EDTG_OVERFLOW, &overflow);
02739     return (overflow);
02740 }
02741 
02742 
02754 void
02755 edt_perror(char *errstr)
02756 {
02757 #ifdef _NT_
02758     LPVOID  lpMsgBuf;
02759 
02760     FormatMessage(
02761         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
02762         NULL,
02763         GetLastError(),
02764         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),      /* Default language */
02765         (LPTSTR) & lpMsgBuf,
02766         0,
02767         NULL
02768         );
02769 
02770     edt_msg(EDTWARN, "%s: %s\n", errstr, lpMsgBuf);
02771 #else
02772     edt_msg_perror(EDTWARN, errstr);
02773 #endif
02774 }
02775 
02792 u_int
02793 edt_errno(void)
02794 {
02795 #ifdef _NT_
02796     return GetLastError();
02797 #else 
02798     extern int errno;
02799     return errno;
02800 #endif
02801 }
02802 
02819 uint_t
02820 edt_reg_read(EdtDev * edt_p, uint_t desc)
02821 {
02822     int     ret;
02823     edt_buf buf = {0, 0};
02824 
02825 
02826 #ifdef USB
02827     if (EDT_REG_TYPE(desc) == REMOTE_USB_TYPE)
02828     {
02829         buf.value = usb_reg_read(edt_p, desc) ;
02830     }
02831     else
02832 #endif /* USB */
02833     {
02834         buf.desc = desc;
02835         ret = edt_ioctl(edt_p, EDTG_REG, &buf);
02836         if (ret < 0)
02837             return ret;
02838     }
02839 
02840     if (dump_reg_access && 
02841         desc != 0x04000084 &&
02842         desc != 0x01010040 &&
02843         desc != 0x01010042)
02844         printf("reg read %08x %08x\n", desc, (uint_t) buf.value);
02845     return (u_int) buf.value;
02846 }
02847 
02863 uint_t
02864 edt_reg_or(EdtDev * edt_p, uint_t desc, uint_t mask)
02865 {
02866     int     ret;
02867     uint_t  val;
02868     edt_buf buf;
02869 
02870     buf.desc = desc;
02871     buf.value = mask;
02872     ret = edt_ioctl(edt_p, EDTS_REG_OR, &buf);
02873     if (ret < 0)
02874         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_OR)");
02875 
02876     if (dump_reg_access && 
02877         desc != 0x04000084 &&
02878         desc != 0x01010040 &&
02879         desc != 0x01010042)
02880         printf("reg or %08x %02x\n", desc, mask);
02881     val = (u_int) buf.value;
02882     return val;
02883 
02884 }
02885 
02901 uint_t
02902 edt_reg_and(EdtDev * edt_p, uint_t desc, uint_t mask)
02903 {
02904     int     ret;
02905     uint_t  val;
02906     edt_buf buf;
02907 
02908     buf.desc = desc;
02909     buf.value = mask;
02910     ret = edt_ioctl(edt_p, EDTS_REG_AND, &buf);
02911     if (ret < 0)
02912         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_AND)");
02913 
02914     if (dump_reg_access && 
02915         desc != 0x04000084 &&
02916         desc != 0x01010040 &&
02917         desc != 0x01010042)
02918         printf("reg and %08x %02x\n", desc, mask);
02919     val = (u_int) buf.value;
02920     return val;
02921 }
02922 
02935 void
02936 edt_reg_clearset(EdtDev * edt_p, uint_t desc, uint_t mask)
02937 {
02938     int     ret;
02939     edt_buf buf;
02940 
02941     buf.desc = desc;
02942     buf.value = mask;
02943     ret = edt_ioctl(edt_p, EDTS_REG_BIT_CLEARSET, &buf);
02944     if (ret < 0)
02945         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_BIT_CLEARSET)");
02946 
02947     return;
02948 }
02949 
02961 void
02962 edt_reg_setclear(EdtDev * edt_p, uint_t desc, uint_t mask)
02963 {
02964     int     ret;
02965     edt_buf buf;
02966 
02967     buf.desc = desc;
02968     buf.value = mask;
02969     ret = edt_ioctl(edt_p, EDTS_REG_BIT_SETCLEAR, &buf);
02970     if (ret < 0)
02971         edt_msg_perror(EDTFATAL, "edt_ioctl(EDT_REG_BIT_SETCLEAR)");
02972 
02973     return;
02974 }
02975 
02992 void
02993 edt_reg_write(EdtDev * edt_p, uint_t desc, uint_t value)
02994 {
02995     int     ret;
02996     edt_buf buf;
02997 
02998 #ifdef USB
02999     if (edt_p->devtype == USB_ID)
03000     {
03001         usb_reg_write(edt_p, desc, value) ;
03002     }
03003     else
03004 #endif /* USB */
03005     {
03006         buf.desc = desc;
03007         buf.value = value;
03008 
03009         ret = edt_ioctl(edt_p, EDTS_REG, &buf);
03010         if (ret < 0)
03011             edt_msg_perror(EDTFATAL, "write");
03012 
03013         if (dump_reg_access && 
03014             desc != 0x04000084 &&
03015             desc != 0x01010040 &&
03016             desc != 0x01010042)
03017             printf("reg write %08x %02x\n", desc, value);
03018     }
03019 }
03020 
03043 void
03044 edt_startdma_action(EdtDev * edt_p, uint_t val)
03045 {
03046     (void) edt_ioctl(edt_p, EDTS_STARTACT, &val);
03047 }
03048 
03079 void
03080 edt_enddma_action(EdtDev * edt_p, uint_t val)
03081 {
03082     (void) edt_ioctl(edt_p, EDTS_ENDACT, &val);
03083 }
03084 
03104 void
03105 edt_startdma_reg(EdtDev * edt_p, uint_t desc, uint_t val)
03106 {
03107     int     ret;
03108     edt_buf buf;
03109 
03110     buf.desc = desc;
03111     buf.value = val;
03112     ret = edt_ioctl(edt_p, EDTS_STARTDMA, &buf);
03113     if (ret < 0)
03114         edt_msg_perror(EDTFATAL, "write");
03115 }
03116 
03129 void
03130 edt_enddma_reg(EdtDev * edt_p, uint_t desc, uint_t val)
03131 {
03132     int     ret;
03133     edt_buf buf;
03134 
03135     buf.desc = desc;
03136     buf.value = val;
03137     ret = edt_ioctl(edt_p, EDTS_ENDDMA, &buf);
03138     if (ret < 0)
03139         edt_msg_perror(EDTFATAL, "write");
03140 }
03141 
03142 
03143 
03175 void
03176 edt_read_start_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03177         u_char set, u_char clear, u_char setclear, u_char clearset,
03178         int delay1, int delay2)
03179 {
03180     edt_buf buf;
03181     u_int delays;
03182 
03183     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03184     (void) edt_ioctl(edt_p, EDTS_READ_START_DELAYS, &delays);
03185 
03186     buf.flags = enable;
03187     buf.desc  = reg_desc;
03188     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03189 
03190     (void) edt_ioctl(edt_p, EDTS_READ_STARTACT, &buf);
03191 }
03192 
03193 
03194 
03226 void
03227 edt_read_end_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03228         u_char set, u_char clear, u_char setclear, u_char clearset,
03229         int delay1, int delay2)
03230 {
03231     edt_buf buf;
03232     u_int delays;
03233 
03234     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03235     (void) edt_ioctl(edt_p, EDTS_READ_END_DELAYS, &delays);
03236 
03237     buf.flags = enable;
03238     buf.desc  = reg_desc;
03239     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03240 
03241     (void) edt_ioctl(edt_p, EDTS_READ_ENDACT, &buf);
03242 }
03243 
03244 
03245 
03277 void
03278 edt_write_start_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03279         u_char set, u_char clear, u_char setclear, u_char clearset,
03280         int delay1, int delay2)
03281 {
03282     edt_buf buf;
03283     u_int delays;
03284 
03285     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03286     (void) edt_ioctl(edt_p, EDTS_WRITE_START_DELAYS, &delays);
03287 
03288     buf.flags = enable;
03289     buf.desc  = reg_desc;
03290     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03291 
03292     (void) edt_ioctl(edt_p, EDTS_WRITE_STARTACT, &buf);
03293 }
03294 
03295 
03296 
03328 void
03329 edt_write_end_action(EdtDev * edt_p, u_int enable, u_int reg_desc,
03330         u_char set, u_char clear, u_char setclear, u_char clearset,
03331         int delay1, int delay2)
03332 {
03333     edt_buf buf;
03334     u_int delays;
03335 
03336     delays = ((delay1 << 16) & 0xffff0000) | (delay2 & 0xffff);
03337     (void) edt_ioctl(edt_p, EDTS_WRITE_END_DELAYS, &delays);
03338 
03339     buf.flags = enable;
03340     buf.desc  = reg_desc;
03341     buf.value = set | (clear << 8) | (setclear << 16) | (clearset << 24);
03342 
03343     (void) edt_ioctl(edt_p, EDTS_WRITE_ENDACT, &buf);
03344 }
03345 
03346 
03347 
03368 u_char
03369 edt_intfc_read(EdtDev * edt_p, uint_t offset)
03370 {
03371     u_int   read;
03372 
03373     read = edt_reg_read(edt_p, INTFC_BYTE | (offset & 0xffff));
03374     return ((u_char) read & 0xff);
03375 }
03376 
03398 void
03399 edt_intfc_write(EdtDev * edt_p, uint_t offset, u_char data)
03400 {
03401     edt_reg_write(edt_p, INTFC_BYTE | (offset & 0xffff), data);
03402 }
03403 
03438 u_short
03439 edt_intfc_read_short(EdtDev * edt_p, uint_t offset)
03440 {
03441     u_int   read;
03442 
03443     read = edt_reg_read(edt_p, INTFC_WORD | (offset & 0xffff));
03444     return (read & 0xffff);
03445 }
03446 
03469 void
03470 edt_intfc_write_short(EdtDev * edt_p, uint_t offset, u_short data)
03471 {
03472     edt_reg_write(edt_p, INTFC_WORD | (offset & 0xffff), data);
03473 }
03474 
03489 uint_t
03490 edt_intfc_read_32(EdtDev * edt_p, uint_t offset)
03491 {
03492     uint_t  read;
03493 
03494     read = edt_reg_read(edt_p, INTFC_32 | (offset & 0xffff));
03495     return (read);
03496 }
03497 
03513 void
03514 edt_intfc_write_32(EdtDev * edt_p, uint_t offset, uint_t data)
03515 {
03516     edt_reg_write(edt_p, INTFC_32 | (offset & 0xffff), data);
03517 }
03518 
03519 
03520 int 
03521 edt_set_rci_chan(EdtDev *edt_p, int unit, int channel)
03522 {
03523     int ret ;
03524     edt_buf buf;
03525     buf.desc = unit;
03526     buf.value = channel;
03527     edt_msg(EDTDEBUG, "set rci unit %d chan %d\n",unit,channel) ;
03528     ret = edt_ioctl(edt_p, EDTS_RCI_CHAN, &buf);
03529     return (ret) ;
03530 }
03531 
03532 int 
03533 edt_get_rci_chan(EdtDev *edt_p, int unit)
03534 {
03535     int channel ;
03536     edt_buf buf;
03537     buf.desc = unit;
03538     edt_ioctl(edt_p, EDTG_RCI_CHAN, &buf);
03539     channel = (u_int) buf.value ;
03540     edt_msg(EDTDEBUG, "get rci unit %d chan %d\n",unit,channel) ;
03541     return (channel) ;
03542 }
03543 
03544 int
03545 edt_set_rci_dma(EdtDev * edt_p, int unit, int channel)
03546 
03547 {
03548     char msg[5];
03549     sprintf(msg,"D %d",channel);
03550 
03551     edt_send_msg(edt_p,unit,msg,3);
03552     edt_set_rci_chan(edt_p, unit, channel) ;
03553 
03554     return 0;
03555 }
03556 
03557 int
03558 edt_get_rci_dma(EdtDev * edt_p, int unit)
03559 
03560 {
03561     char msgbuf[5];
03562     int channel;
03563     msgbuf[1] = 0;
03564 
03565     edt_send_msg(edt_p, unit, "D", 1);
03566     edt_serial_wait(edt_p, 100, 0) ;
03567     edt_get_msg(edt_p, msgbuf, sizeof(msgbuf));
03568 
03569     channel = atoi(&msgbuf[2]);
03570 
03571     return channel;
03572 
03573 }
03574 
03575 int
03576 edt_set_foiunit(EdtDev * edt_p, int val)
03577 {
03578     edt_p->foi_unit = val;
03579     return (edt_ioctl(edt_p, EDTS_FOIUNIT, &val));
03580 }
03581 
03582 /*
03583 * OBSOLETE (FOI no longer supported).
03584 *
03585 * Returns the number of RCI modules connected to the EDT FOI (fiber
03586 * optic interface) board.
03587 */
03588 int
03589 edt_get_foiunit(EdtDev * edt_p)
03590 {
03591     int     unit;
03592 
03593     edt_ioctl(edt_p, EDTG_FOIUNIT, &unit);
03594     return (unit);
03595 }
03596 
03597 /*
03598 * OBSOLETE (FOI no longer supported).
03599 *
03600 * sets which RCI unit to address with subsequent serial and register 
03601 * read/write functions
03602 *
03603 * @param edt_p:    device struct returned from edt_open
03604 *        unit:     unit number of RCI unit
03605 *
03606 * @return 0 on success; -1 on failure
03607 */
03608 
03609 int
03610 edt_set_foicount(EdtDev * edt_p, int val)
03611 {
03612     return (edt_ioctl(edt_p, EDTS_FOICOUNT, &val));
03613 }
03614 
03625 int
03626 edt_get_foicount(EdtDev * edt_p)
03627 {
03628     int     val;
03629 
03630     edt_ioctl(edt_p, EDTG_FOICOUNT, &val);
03631     return (val);
03632 }
03633 
03648 int
03649 edt_set_burst_enable(EdtDev * edt_p, int onoff)
03650 {
03651     return (edt_ioctl(edt_p, EDTS_BURST_EN, &onoff));
03652 }
03653 
03654 
03668 int
03669 edt_get_burst_enable(EdtDev * edt_p)
03670 {
03671     int     val;
03672 
03673     edt_ioctl(edt_p, EDTG_BURST_EN, &val);
03674     return (val);
03675 }
03676 
03677 int
03678 edt_set_continuous(EdtDev * edt_p, int val)
03679 {
03680 #ifdef PDV
03681     u_int tmp ;
03682     tmp = edt_p->dd_p->datapath_reg ;
03683     /* tmp = edt_reg_read(edt_p, PDV_DATA_PATH) & ~PDV_CONTINUOUS ;*/
03684     edt_ioctl(edt_p, EDTS_PDVDPATH, &tmp);
03685     return (edt_ioctl(edt_p, EDTS_PDVCONT, &val));
03686 #else
03687     return 0;
03688 #endif
03689 }
03690 
03691 void
03692 edt_foi_autoconfig(EdtDev * edt_p)
03693 {
03694     edt_reset_serial(edt_p);
03695     edt_set_foicount(edt_p, 0);
03696     edt_check_foi(edt_p);
03697 }
03698 
03699 void
03700 edt_reset_counts(EdtDev * edt_p)
03701 {
03702     int     dmy;
03703 
03704     edt_ioctl(edt_p, EDTS_RESETCOUNT, &dmy);
03705 }
03706 
03707 void
03708 edt_reset_serial(EdtDev * edt_p)
03709 {
03710     int     dmy;
03711 
03712     dmy = edt_p->foi_unit ;
03713     edt_ioctl(edt_p, EDTS_RESETSERIAL, &dmy);
03714 }
03715 
03716 #if defined( PCD ) || defined(UCD) || defined(PDV)
03717 
03718 u_char
03719 pcd_get_option(EdtDev * edt_p)
03720 {
03721     return (edt_intfc_read(edt_p, PCD_OPTION));
03722 }
03723 
03724 u_char
03725 pcd_get_cmd(EdtDev * edt_p)
03726 {
03727     return (edt_intfc_read(edt_p, PCD_CMD));
03728 }
03729 
03730 void
03731 pcd_set_cmd(EdtDev * edt_p, u_char val)
03732 {
03733     edt_intfc_write(edt_p, PCD_CMD, val);
03734 }
03735 
03736 u_char
03737 pcd_get_funct(EdtDev * edt_p)
03738 {
03739     return (edt_intfc_read(edt_p, PCD_FUNCT));
03740 }
03741 
03742 void
03743 pcd_set_funct(EdtDev * edt_p, u_char val)
03744 {
03745     edt_intfc_write(edt_p, PCD_FUNCT, val);
03746 }
03747 
03748 u_char
03749 pcd_get_stat(EdtDev * edt_p)
03750 {
03751     return ((u_char) edt_intfc_read(edt_p, PCD_STAT));
03752 }
03753 
03754 u_char
03755 pcd_get_stat_polarity(EdtDev * edt_p)
03756 {
03757     return (edt_intfc_read(edt_p, PCD_STAT_POLARITY));
03758 }
03759 
03760 void
03761 pcd_set_stat_polarity(EdtDev * edt_p, u_char val)
03762 {
03763     edt_intfc_write(edt_p, PCD_STAT_POLARITY, val);
03764 }
03765 
03766 void
03767 pcd_set_byteswap(EdtDev * edt_p, int val)
03768 {
03769     u_char  tmp;
03770 
03771     tmp = edt_intfc_read(edt_p, PCD_CONFIG);
03772     if (val)
03773         tmp |= PCD_BYTESWAP;
03774     else
03775         tmp &= ~PCD_BYTESWAP;
03776     edt_intfc_write(edt_p, PCD_CONFIG, tmp);
03777 }
03778 
03779 
03780 void
03781 edt_flush_channel(EdtDev *edt_p, int channel)
03782 
03783 {
03784     u_int dma_cfg = edt_reg_read(edt_p, EDT_DMA_CFG) ;
03785 
03786     dma_cfg &= ~(EDT_EMPTY_CHAN | EDT_EMPTY_CHAN_FIFO) ;
03787 
03788     /*
03789     * Set the channel number and enable the rfifo and related logic.
03790     */
03791     dma_cfg |= ((channel << EDT_EMPTY_CHAN_SHIFT) | EDT_RFIFO_ENB) ;
03792     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03793 
03794     /*
03795     * Set then reset the channel fifo flush bit.
03796     */
03797     dma_cfg |= EDT_EMPTY_CHAN_FIFO ;
03798     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03799 
03800     dma_cfg &= ~EDT_EMPTY_CHAN_FIFO ;
03801     edt_reg_write(edt_p, EDT_DMA_CFG, dma_cfg) ;
03802 
03803 
03804 }
03805 
03806 
03807 
03808 void
03809 pcd_flush_channel(EdtDev * edt_p, int channel)
03810 {
03811     u_short ssd16_chen = edt_reg_read(edt_p, SSD16_CHEN) ;
03812 
03813     ssd16_chen &= ~(1 << channel);
03814     edt_reg_write(edt_p, SSD16_CHEN, ssd16_chen) ;
03815 
03816     edt_flush_channel(edt_p,channel);
03817 
03818 
03819     ssd16_chen |= (1 << channel);
03820     edt_reg_write(edt_p, SSD16_CHEN, ssd16_chen) ;
03821 
03822 }
03823 
03824 /*****************************************************************************
03825 *
03826 * pio routines:  programmed I/O for PCD DMA boards.
03827 *
03828 *****************************************************************************/
03829 
03830 static volatile u_int  *reg_fifo_io  = NULL ;
03831 static volatile u_char *reg_fifo_cnt = NULL ;
03832 static volatile u_char *reg_fifo_ctl = NULL ;
03833 static volatile u_char *reg_intfc_off ;         /* mmap to intfc regs      */
03834 static volatile u_char *reg_intfc_dat ;         /* mmap to intfc regs      */
03835 static volatile int io_direction = -1 ;
03836 
03837 void
03838 pcd_pio_intfc_write(EdtDev *edt_p, u_int desc, u_char val) 
03839 {
03840     int dmy ;
03841 
03842     *reg_intfc_off = desc & 0xff ;
03843     dmy = *reg_intfc_off ;
03844 
03845     *reg_intfc_dat = val ;
03846     dmy = *reg_intfc_dat ;
03847 }
03848 
03849 u_char
03850 pcd_pio_intfc_read(EdtDev *edt_p, u_int desc) 
03851 {
03852     int dmy ;
03853 
03854     *reg_intfc_off = desc & 0xff ;
03855     dmy = *reg_intfc_off ;
03856 
03857     return(*reg_intfc_dat) ;
03858 }
03859 
03860 
03861 
03862 void
03863 pcd_pio_set_direction(EdtDev *edt_p, int direction)
03864 {
03865     u_char  cmd = pcd_pio_intfc_read(edt_p, PCD_CMD) ;
03866 
03867     if (direction)
03868     {
03869         pcd_pio_intfc_write(edt_p, PCD_DIRA, 0x0f);
03870 
03871         cmd &= ~PCD_DIR;
03872         cmd |= PCD_ENABLE;
03873 
03874     }
03875     else
03876     {
03877         pcd_pio_intfc_write(edt_p, PCD_DIRA, 0xf0);
03878 
03879         cmd |= PCD_DIR | PCD_ENABLE ;
03880     }
03881 
03882     pcd_pio_intfc_write(edt_p, PCD_CMD, cmd);
03883 }
03884 
03885 static void
03886 pcd_pio_quick_flush(EdtDev *edt_p)
03887 {
03888     u_char tmpc ;
03889 
03890     tmpc = *reg_fifo_ctl ;
03891     tmpc &= ~1 ;
03892     *reg_fifo_ctl = tmpc ;
03893     tmpc |= 1 ;
03894     *reg_fifo_ctl = tmpc ;
03895 }
03896 
03897 
03898 void
03899 pcd_pio_flush_fifo(EdtDev * edt_p)
03900 {
03901     unsigned char cmd;
03902     unsigned int dmy;
03903 
03904     /* reset the interface fifos */
03905     *reg_intfc_off = PCD_CMD & 0xff ;
03906     dmy = *reg_intfc_off ;
03907     cmd = *reg_intfc_dat ;
03908     cmd &= ~PCD_ENABLE;
03909     *reg_intfc_dat = cmd ;
03910     dmy = *reg_intfc_dat ;
03911     cmd |= PCD_ENABLE;
03912     *reg_intfc_dat = cmd ;
03913     dmy = *reg_intfc_dat ;
03914 
03915     pcd_pio_quick_flush(edt_p) ;
03916 
03917 }
03918 
03919 void
03920 pcd_pio_init(EdtDev *edt_p)
03921 {
03922     static u_char * mapaddr = 0 ;
03923 
03924     if (mapaddr == 0)
03925     {
03926         mapaddr = (u_char *) edt_mapmem(edt_p, 0, 256) ;
03927         reg_fifo_io  = (u_int *)(mapaddr + (EDT_GP_OUTPUT & 0xff)) ;
03928         reg_fifo_cnt  = (u_char *)(mapaddr + (EDT_DMA_CFG & 0xff) + 3) ;
03929         reg_fifo_ctl = (u_char *)(mapaddr + (EDT_DMA_CFG & 0xff) + 1) ;
03930         reg_intfc_off  = (volatile u_char *) mapaddr + (EDT_REMOTE_OFFSET & 0xff) ;
03931         reg_intfc_dat = (volatile u_char *) mapaddr + (EDT_REMOTE_DATA & 0xff) ;
03932     }
03933     pcd_pio_intfc_write(edt_p, PCD_DIRB, 0xcc);
03934     pcd_pio_flush_fifo(edt_p) ;
03935 }
03936 
03937 int
03938 pcd_pio_write(EdtDev *edt_p, u_char *buf, int size)
03939 {
03940     int i;
03941     u_int *tmpl = (u_int *) buf ;
03942 
03943     pcd_pio_set_direction(edt_p, EDT_WRITE) ;
03944 
03945     for (i = 0 ; i < size / 4 ; i++) 
03946         *reg_fifo_io = *tmpl++ ;
03947 
03948     return(size);
03949 }
03950 
03951 int
03952 pcd_pio_read(EdtDev *edt_p, u_char *buf, int size)
03953 {
03954     u_int *tmpl = (u_int *) buf ;
03955     int wordcnt = 0 ;
03956     int words_avail ;
03957     int words_requested = size / 4 ;
03958 
03959     pcd_pio_set_direction(edt_p, EDT_READ) ;
03960 
03961     while (wordcnt < words_requested)
03962     {
03963         words_avail = *reg_fifo_cnt & 0xf ;
03964 
03965         while (words_avail && wordcnt < words_requested)
03966         {
03967             -- words_avail ;
03968             *tmpl = *reg_fifo_io ;
03969             wordcnt++ ;
03970             tmpl++ ;
03971         }
03972 
03973         if ((wordcnt == words_requested - 1) && (*reg_fifo_cnt & 0x1f) == 0x10)
03974         {
03975             *tmpl = *reg_fifo_io ;
03976             wordcnt++ ;
03977         }
03978     }
03979 
03980     pcd_pio_quick_flush(edt_p);
03981 
03982     return(size) ;
03983 }
03984 
03985 void
03986 pcd_set_abortdma_onintr(EdtDev *edt_p, int flag)
03987 {
03988     if (flag == 0)
03989     {
03990         edt_reg_and(edt_p, PCD_CMD, ~PCD_STAT_INT_1) ;
03991     }
03992 
03993     edt_ioctl(edt_p, EDTS_ABORTDMA_ONINTR, &flag) ;
03994 
03995     if (flag)
03996     {
03997         edt_reg_or(edt_p, PCD_CMD, PCD_STAT_INT_1 | PCD_ENABLE) ;
03998         edt_reg_or(edt_p, PCD_STAT_POLARITY, PCD_STAT_INT_ENA) ;
03999         edt_reg_or(edt_p, EDT_DMA_INTCFG, EDT_RMT_EN_INTR | EDT_PCI_EN_INTR) ; 
04000     }
04001 }
04002 
04003 #endif                          /* PCD */
04004 
04005 
04006 
04015 void
04016 edt_flush_fifo(EdtDev * edt_p)
04017 {
04018     uint_t  tmp;
04019     unsigned char cmd;
04020     unsigned char cfg;
04021     unsigned int dmy;
04022 
04023     edt_msg(EDTDEBUG, "edt_flush_fifo\n") ;
04024     /* Turn off the PCI fifo */
04025     tmp = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04026     tmp &= (~EDT_RFIFO_ENB);
04027     edt_reg_write(edt_p, EDT_DMA_INTCFG, tmp);
04028     dmy = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04029 
04030     if (edt_is_pcd(edt_p) || edt_p->devid == PDVAERO_ID)
04031     {
04032         /* reset the interface fifos */
04033         cmd = edt_intfc_read(edt_p, PCD_CMD);
04034         cmd &= ~PCD_ENABLE;
04035         edt_intfc_write(edt_p, PCD_CMD, cmd);
04036         dmy = edt_intfc_read(edt_p, PCD_CMD);
04037         cmd |= PCD_ENABLE;
04038         edt_intfc_write(edt_p, PCD_CMD, cmd);
04039         dmy = edt_intfc_read(edt_p, PCD_CMD);
04040     }
04041     else if (edt_is_pdv(edt_p))
04042     {
04043         if (edt_p->devid == PDVFOI_ID)
04044         {
04045             edt_p->foi_unit = edt_get_foiunit(edt_p);
04046             edt_init_mac8100(edt_p) ;
04047             edt_send_msg(edt_p, edt_p->foi_unit, "z", 1);
04048             edt_intfc_write(edt_p, PDV_CMD, PDV_RESET_INTFC);
04049         }
04050         else
04051         {
04052             int cont = edt_reg_read(edt_p, PDV_DATA_PATH) & PDV_CONTINUOUS;
04053 
04054             cfg = edt_intfc_read(edt_p, PDV_CFG);
04055             cfg &= ~PDV_FIFO_RESET;
04056             edt_intfc_write(edt_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
04057             edt_intfc_write(edt_p, PDV_CMD, PDV_RESET_INTFC);
04058             edt_intfc_write(edt_p, PDV_CFG, cfg);
04059 
04060             if (cont)
04061                 edt_reg_or(edt_p,PDV_DATA_PATH, PDV_CONTINUOUS);
04062         }
04063     }
04064 
04065 
04066     /* Turn     on the PCI fifos, which flushes them */
04067     tmp |= (EDT_RFIFO_ENB);
04068     edt_reg_write(edt_p, EDT_DMA_INTCFG, tmp);
04069     dmy = edt_reg_read(edt_p, EDT_DMA_INTCFG);
04070 
04071 }
04072 
04083 uint_t
04084 edt_get_bytecount(EdtDev * edt_p)
04085 {
04086     uint_t  tmp;
04087 
04088     if (edt_ioctl(edt_p, EDTG_BYTECOUNT, &tmp) < 0)
04089         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_BYTECOUNT)");
04090 
04091     return (tmp);
04092 }
04093 
04103 uint_t
04104 edt_get_timeout_count(EdtDev * edt_p)
04105 {
04106     uint_t  tmp;
04107 
04108     if (edt_ioctl(edt_p, EDTG_TIMECOUNT, &tmp) < 0)
04109         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_TIMECOUNT)");
04110 
04111     return (tmp);
04112 }
04117 unsigned short
04118 edt_get_direction(EdtDev * edt_p)
04119 {
04120     unsigned short dirreg;
04121 
04122     /* Set the direction register for DMA output */
04123     dirreg = edt_intfc_read(edt_p, PCD_DIRA);
04124     dirreg |= edt_intfc_read(edt_p, PCD_DIRB) << 8;
04125     return (dirreg);
04126 }
04127 
04138 int
04139 edt_cancel_current_dma(EdtDev * edt_p)
04140 {
04141     unsigned int finish_current = 0;
04142 
04143     return edt_ioctl(edt_p, EDTS_STOPBUF, &finish_current);
04144 }
04145 
04146 
04158 void
04159 edt_set_direction(EdtDev * edt_p, int direction)
04160 {
04161 
04162 
04163     if (edt_is_pcd(edt_p) || edt_p->devid == PDVAERO_ID)
04164     {
04165         edt_ioctl(edt_p, EDTS_DIRECTION, &direction);
04166     }
04167 
04168     edt_p->last_direction = (direction) ? 2: 1;
04169 
04170 }
04171 
04172 /*
04173 * EDT IOCTL Interface Routines
04174 * 
04175 * DESCRIPTION General   Purpose device control layer for EDT PCI and SBus
04176 * interface products
04177 * 
04178 * All routines access a specific device, whose handle is created and returned
04179 * by    the <device>_open() routine.
04180 */
04181 
04182 
04183 #ifndef TRUE
04184 #define TRUE 1
04185 #endif
04186 #ifndef FALSE
04187 #define FALSE 0
04188 #endif
04189 
04190 
04200 int
04201 edt_ioctl(EdtDev * edt_p, int code, void *arg)
04202 {
04203     int     get, set;
04204     int     size;
04205     edt_ioctl_struct eis;
04206 #ifdef __APPLE__
04207     int     ret ;
04208 #endif
04209 
04210 #if 0 /* produces too much output for the normal case, but may still be useful...*/
04211     edt_msg(EDTDEBUG, "edt_ioctl(%04x, %04x)\n", code, arg);
04212 #endif
04213 
04214     if (edt_p->devid == DMY_ID)
04215         return (0);
04216     eis.device = edt_p->fd;
04217     eis.controlCode = EIO_DECODE_ACTION(code);
04218     size = EIO_DECODE_SIZE(code);
04219     set = EIO_DECODE_SET(code);
04220     get = EIO_DECODE_GET(code);
04221     eis.inSize = 0;
04222     eis.inBuffer = NULL;
04223     eis.outSize = 0;
04224     eis.outBuffer = NULL;
04225     eis.bytesReturned = 0 ;
04226 #ifdef __APPLE__
04227     eis.channel = edt_p->channel_no ;
04228     eis.unit = edt_p->unit_no ;
04229 #endif
04230 
04231 
04232     if (set)
04233     {
04234         eis.inSize = size;
04235         eis.inBuffer = arg;
04236     }
04237 
04238     if (get)
04239     {
04240         eis.outSize = size;
04241         eis.outBuffer = arg;
04242     }
04243 
04244 
04245 #ifdef _NT_
04246 
04247     if (!DeviceIoControl(
04248         (HANDLE) edt_p->fd,
04249         EDT_MAKE_IOCTL(EDT_DEVICE_TYPE, eis.controlCode),
04250         eis.inBuffer,
04251         eis.inSize,
04252         eis.outBuffer,
04253         eis.outSize,
04254         &eis.bytesReturned,
04255         NULL))
04256     {
04257         return -1;
04258     }
04259     return 0;
04260 
04261 #else
04262 #ifdef VXWORKS
04263     return ioctl(edt_p->fd, EDT_NT_IOCTL, (int)&eis);
04264 #else
04265 #if defined(__APPLE__)
04266 
04267     eis.device = edt_p->channel_no ;
04268     ret = edt_mac_ioctl((u_int)edt_p->fd, EDT_NT_IOCTL, &eis) ;
04269     return(ret);
04270 #else
04271     return ioctl(edt_p->fd, EDT_NT_IOCTL, &eis);
04272 #endif /* apple */
04273 #endif
04274 #endif
04275 
04276 }
04277 
04278 int
04279 edt_ioctl_nt(EdtDev * edt_p, int controlCode, void *inBuffer, int inSize,
04280              void *outBuffer, int outSize, int *bytesReturned)
04281 {
04282     int     ret = 0;
04283 
04284     edt_ioctl_struct eis;
04285 
04286     eis.device = edt_p->fd;
04287     eis.controlCode = controlCode;
04288     eis.inBuffer = inBuffer;
04289     eis.inSize = inSize;
04290     eis.outBuffer = outBuffer;
04291     eis.outSize = outSize;
04292     eis.bytesReturned = 0;
04293 #ifdef __APPLE__
04294     eis.channel = edt_p->channel_no ;
04295     eis.unit = edt_p->unit_no ;
04296 #endif
04297 
04298 #ifdef _NT_
04299 
04300     if (inSize == 0 && outSize == 0)
04301         return ret ;
04302 
04303     if (!DeviceIoControl(
04304         eis.device,
04305         eis.controlCode,
04306         eis.inBuffer,
04307         eis.inSize,
04308         eis.outBuffer,
04309         eis.outSize,
04310         &eis.bytesReturned,
04311         NULL))
04312     {
04313 
04314     }
04315 
04316 #else
04317 #ifdef VXWORKS
04318     if ((ret = ioctl(eis.device, EDT_NT_IOCTL, (int)&eis)) == 0)
04319 #else /* vxworks */
04320 #if defined(__APPLE__)
04321     if ((ret = edt_mac_ioctl((u_int)edt_p->fd, EDT_NT_IOCTL, &eis)) == 0)
04322 #else
04323     if ((ret = ioctl(eis.device, EDT_NT_IOCTL, &eis)) == 0)
04324 #endif /* apple */
04325 #endif /* vxworks */
04326 #endif /* nt */
04327     {
04328         *bytesReturned = eis.bytesReturned;
04329     }
04330     return ret;
04331 }
04332 
04333 
04334 uint_t
04335 edt_debugval(EdtDev * edt_p)
04336 {
04337     uint_t  debugval;
04338 
04339     edt_ioctl(edt_p, EDTG_DEBUGVAL, &debugval);
04340     return (debugval);
04341 }
04342 
04354 int
04355 edt_timeouts(EdtDev * edt_p)
04356 {
04357     int     timeouts;
04358 
04359     if (edt_p->devid == DMY_ID)
04360         return (0);
04361     edt_ioctl(edt_p, EDTG_TIMEOUTS, &timeouts);
04362     return (timeouts);
04363 }
04364 
04365 int
04366 edt_set_dependent(EdtDev * edt_p, void *addr)
04367 {
04368     if (addr == NULL)
04369         return (-1);
04370     if (edt_p->devid == DMY_ID)
04371     {
04372 #ifdef _NT_
04373         edt_p->fd = CreateFile(
04374             edt_p->edt_devname,
04375             GENERIC_READ | GENERIC_WRITE,
04376             FILE_SHARE_READ | FILE_SHARE_WRITE,
04377             NULL,
04378             OPEN_ALWAYS,
04379             FILE_ATTRIBUTE_NORMAL,
04380             NULL);
04381 #else
04382         if (edt_p->fd)
04383         {
04384             /* printf("fd already open\n") ;*/
04385         }
04386         else
04387         {
04388             edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666);
04389         }
04390 #endif
04391         edt_write(edt_p, addr, sizeof(Dependent));
04392 #ifdef _NT_
04393         CloseHandle(edt_p->fd);
04394         edt_p->fd = NULL;
04395 #else
04396         close(edt_p->fd);
04397         edt_p->fd = 0;
04398 #endif
04399         return (0);
04400     }
04401     return (edt_ioctl(edt_p, EDTS_DEPENDENT, addr));
04402 }
04403 
04404 int
04405 edt_get_dependent(EdtDev * edt_p, void *addr)
04406 {
04407     if (addr == NULL)
04408         return (-1);
04409     if (edt_p->devid == DMY_ID)
04410     {
04411         int ret ;
04412 #ifdef _NT_
04413         edt_p->fd = CreateFile(
04414             edt_p->edt_devname,
04415             GENERIC_READ | GENERIC_WRITE,
04416             FILE_SHARE_READ | FILE_SHARE_WRITE,
04417             NULL,
04418             OPEN_ALWAYS,
04419             FILE_ATTRIBUTE_NORMAL,
04420             NULL);
04421 #else
04422         edt_p->fd = open(edt_p->edt_devname, O_RDWR, 0666);
04423 #endif
04424         ret = edt_read(edt_p, addr, sizeof(Dependent));
04425 #ifdef _NT_
04426         CloseHandle(edt_p->fd);
04427         edt_p->fd = NULL;
04428 #else
04429         close(edt_p->fd);
04430         edt_p->fd = 0;
04431 #endif
04432         if (ret != sizeof(Dependent))
04433             return (-1) ;
04434         return (0);
04435     }
04436     return (edt_ioctl(edt_p, EDTG_DEPENDENT, addr));
04437 }
04438 
04439 int
04440 edt_dump_sglist( EdtDev * edt_p, int val)
04441 {
04442     return (edt_ioctl(edt_p, EDTS_DUMP_SGLIST, &val));
04443 }
04444 
04445 int
04446 edt_set_debug(EdtDev * edt_p, int val)
04447 {
04448     return (edt_ioctl(edt_p, EDTS_DEBUG, &val));
04449 }
04450 
04451 int
04452 edt_get_debug(EdtDev * edt_p)
04453 {
04454     int     val;
04455 
04456     edt_ioctl(edt_p, EDTG_DEBUG, &val);
04457     return (val);
04458 }
04459 
04473 int
04474 edt_set_rtimeout(EdtDev * edt_p, int value)
04475 {
04476     edt_msg(EDTDEBUG, "edt_set_rtimeout(%d)\n", value);
04477     return edt_ioctl(edt_p, EDTS_RTIMEOUT, &value);
04478 }
04479 
04495 int
04496 edt_set_wtimeout(EdtDev * edt_p, int value)
04497 {
04498     edt_msg(EDTDEBUG, "edt_set_wtimeout(%d)\n", value);
04499     return edt_ioctl(edt_p, EDTS_WTIMEOUT, &value);
04500 }
04501 
04513 int
04514 edt_get_rtimeout(EdtDev * edt_p)
04515 {
04516     int     value;
04517 
04518     edt_ioctl(edt_p, EDTG_RTIMEOUT, &value);
04519     return (value);
04520 }
04521 
04533 int
04534 edt_get_wtimeout(EdtDev * edt_p)
04535 {
04536     int     value;
04537 
04538     edt_ioctl(edt_p, EDTG_WTIMEOUT, &value);
04539     return (value);
04540 }
04541 
04542 int
04543 edt_get_tracebuf(EdtDev * edt_p, u_int * addr)
04544 {
04545     if (addr == NULL)
04546         return (-1);
04547     return (edt_ioctl(edt_p, EDTG_TRACEBUF, addr));
04548 }
04549 
04550 u_short
04551 edt_read_mac8100(EdtDev * edt_p, u_int add)
04552 {
04553     u_int   read;
04554 
04555     read = edt_reg_read(edt_p, MAC8100_WORD | (add & 0xff));
04556     return (read & 0xffff);
04557 }
04558 
04559 void
04560 edt_write_mac8100(EdtDev * edt_p, u_int add, u_short data)
04561 {
04562     edt_reg_write(edt_p, MAC8100_WORD | (add & 0xff), data);
04563 }
04564 
04565 void
04566 edt_send_dma(EdtDev * edt_p, int unit, u_int start_val)
04567 {
04568     u_int   stat;
04569     int     loop = 0;
04570 
04571     stat = edt_reg_read(edt_p, FOI_WR_MSG_STAT);
04572     while ((stat & FOI_MSG_BSY) != 0)
04573     {
04574         if (loop++ > 1000000)
04575         {
04576             edt_msg(EDTDEBUG, "failed send dma stat %x\n", stat);
04577             return;
04578         }
04579         stat = edt_reg_read(edt_p, FOI_WR_MSG_STAT);
04580     }
04581     /* routing byte */
04582     edt_reg_write(edt_p, FOI_WR_MSG_DATA, 0x00 | (unit & 0x1f));
04583     while ((stat & FOI_TX_FIFO_FULL) == 0)
04584     {
04585         edt_reg_write(edt_p, FOI_WR_MSG_DATA, start_val++);
04586 
04587         stat = edt_reg_read(edt_p, FOI_WR_MSG_STAT);
04588     }
04589     edt_reg_write(edt_p, FOI_WR_MSG_STAT, FOI_MSG_SEND);
04590 }
04591 
04592 #define END_MARKER      0xffff
04593 static u_short init_mac8100_data[] = {
04594     0, 0x0,
04595     1, 0x0,
04596     2, 0x0,
04597     3, 0x0,
04598     4, 0x0,
04599     5, 0x0,
04600     6, 0x0,
04601     7, 0x07c2,
04602     /* 7, 0x7d8 */ /* this inserts status and crc */
04603     /* 7, 0x07ca,*/
04604     8, 0x0ec0,
04605     /* 8, 0x800,*/ /* 800 to accept all packets */
04606     9, 0x2400, /* autoclear RXDC, counters roll */
04607     11, 0x0000,
04608     14, 0x8800,
04609     17, 0x843f,
04610     18, 0x0000,
04611     /* 18, 0x4000 */ /* sets receive fifo watermark 1,2 */
04612     19, 0x4000,
04613     20, 0x001f,
04614     21, 0x0000,
04615     END_MARKER, 0x0000
04616 };
04617 
04618 static u_short init_mac8101_data[] = {
04619     7,  0x03e1,
04620     8,  0x0ec0,
04621     9,  0x2400, /* autoclear RXDC, counters roll */
04622     10, 0x0000,
04623     17, 0xf43e,
04624     18, 0xf080,
04625     19, 0x4000,
04626     END_MARKER, 0x0000
04627 };
04628 
04629 void
04630 edt_init_mac8100(EdtDev * edt_p)
04631 {
04632 
04633     int is_mac8101;
04634 
04635     u_short *init_tab = init_mac8100_data;
04636     u_int   tmpcfg;
04637 
04638     /* enable mac8100 */
04639     tmpcfg = edt_reg_read(edt_p, EDT_DMA_CFG);
04640     edt_reg_write(edt_p, EDT_DMA_CFG, tmpcfg | 0x200);
04641     edt_msleep(2) ;
04642 
04643     /* do reset */
04644     edt_write_mac8100(edt_p, 7, 0x8000) ;
04645     /* self clears in 1 usec */
04646     edt_msleep(2) ;
04647 
04648 
04649     /* read a xilinx register? */
04650     (void) edt_reg_read(edt_p, FOI_MSG);
04651 
04652     /* read part ID */
04653     is_mac8101 = edt_read_mac8100(edt_p, 32) & 0x1000;
04654 
04655     if (! is_mac8101)  {
04656         init_tab = init_mac8100_data;                   /* for old 5v PCIFOI */
04657     }
04658     else
04659     {
04660         init_tab = init_mac8101_data;                   /* for new 3v PCIFOI */
04661         edt_reg_write(edt_p, 0x010000c5, 0x02);         /* clr fifo's, inrpts */
04662         edt_reg_write(edt_p, 0x040000d4, 0x80000000);   /* reset Xilinx */
04663         edt_reg_write(edt_p, 0x040000d4, 0x36000000);   /* RXRBDIR + RXBUIG */
04664     }
04665 
04666 
04667     while (*init_tab != END_MARKER)
04668     {
04669         edt_write_mac8100(edt_p, (u_int) * init_tab, *(init_tab + 1));
04670         init_tab += 2;
04671     }
04672     /* reset message fifos */
04673     edt_reg_write(edt_p, FOI_WR_MSG_STAT, FOI_FIFO_FLUSH);
04674 
04675 }
04676 
04677 
04678 
04682 int
04683 edt_send_msg(EdtDev * edt_p, int unit, char *msg, int size)
04684 {
04685     int dummy ;
04686     ser_buf ser ;
04687     ser.unit = unit ;
04688     ser.size = size ;
04689     ser.flags = EDT_SERIAL_SAVERESP ;
04690     memcpy(ser.buf,msg,size) ;
04691 
04692     edt_ioctl_nt(edt_p, ES_SERIAL, &ser, size + EDT_SERBUF_OVRHD,
04693         NULL, 0, &dummy);
04694     return (0);
04695 }
04696 
04697 int
04698 edt_get_msg_unit(EdtDev * edt_p, char *msgbuf, int maxsize, int unit)
04699 {
04700     ser_buf ser ;
04701     int     bytes = 0;
04702     ser.unit = unit ;
04703     ser.size = maxsize ;
04704 
04705     edt_ioctl_nt(edt_p, EG_SERIAL, &ser, EDT_SERBUF_OVRHD,
04706         msgbuf, maxsize, &bytes);
04707     if (bytes < maxsize)
04708         msgbuf[bytes] = '\0';
04709     return (bytes);
04710 }
04711 
04725 int
04726 edt_get_msg(EdtDev * edt_p, char *msgbuf, int maxsize)
04727 {
04728     if (edt_p->devid == PDVFOI_ID)
04729         return(edt_get_msg_unit(edt_p, msgbuf, maxsize, edt_p->foi_unit)) ;
04730     else if (edt_is_dvcl(edt_p) || edt_is_dvfox(edt_p) || edt_p->devid == PDVAERO_ID)
04731         return(edt_get_msg_unit(edt_p, msgbuf, maxsize, edt_p->channel_no)) ;
04732     else return(edt_get_msg_unit(edt_p, msgbuf, maxsize, 0)) ;
04733 }
04734 
04741 double
04742 edt_timestamp()
04743 {
04744     double  dtime;
04745 
04746 #ifdef _NT_
04747     LARGE_INTEGER endtime;
04748     LARGE_INTEGER frequency;
04749 
04750     QueryPerformanceCounter(&endtime);
04751     QueryPerformanceFrequency(&frequency);
04752 
04753     dtime = ((double) endtime.QuadPart) / (double) frequency.QuadPart;
04754 #elif defined(VXWORKS)
04755     struct timespec     endtime ;
04756     clock_gettime(CLOCK_REALTIME,&endtime) ;
04757     dtime = (double) endtime.tv_sec
04758         + (((double) endtime.tv_nsec) / 1000000000.0);
04759 #else                           /* _NT_ */
04760     struct timeval endtime;
04761 
04762     gettimeofday(&endtime, (void *) NULL);
04763 
04764     dtime = (double) endtime.tv_sec
04765         + (((double) endtime.tv_usec) / 1000000.0);
04766 
04767 #endif                          /* _NT_ */
04768 
04769     return (dtime);     
04770 
04771 }
04772 
04774 double
04775 edt_dtime()
04776 {
04777     double  dtime;
04778 
04779 #ifdef _NT_
04780     static LARGE_INTEGER starttime;
04781     LARGE_INTEGER endtime;
04782     LARGE_INTEGER frequency;
04783 
04784     QueryPerformanceCounter(&endtime);
04785     QueryPerformanceFrequency(&frequency);
04786 
04787     dtime = ((double) endtime.QuadPart - (double) starttime.QuadPart)
04788         / (double) frequency.QuadPart;
04789 #elif defined(VXWORKS)
04790     static struct timespec starttime;
04791     struct timespec     endtime ;
04792     double  start;
04793     double  end;
04794     clock_gettime(CLOCK_REALTIME,&endtime) ;
04795     start = (double) starttime.tv_sec
04796         + (((double) starttime.tv_nsec) / 1000000000.0);
04797     end = (double) endtime.tv_sec
04798         + (((double) endtime.tv_nsec) / 1000000000.0);
04799     dtime = end - start;
04800 #else                           /* _NT_ */
04801     static struct timeval starttime;
04802     struct timeval endtime;
04803     double  start;
04804     double  end;
04805 
04806     gettimeofday(&endtime, (void *) NULL);
04807 
04808     start = (double) starttime.tv_sec
04809         + (((double) starttime.tv_usec) / 1000000.0);
04810     end = (double) endtime.tv_sec
04811         + (((double) endtime.tv_usec) / 1000000.0);
04812     dtime = end - start;
04813 
04814 #endif                          /* _NT_ */
04815 
04816     starttime = endtime;
04817     return (dtime);
04818 }
04819 
04820 static double elapsed_start = 0.0;
04821 
04827 double 
04828 edt_elapsed(u_char reset)
04829 {
04830 
04831     if (reset || elapsed_start == 0.0)
04832     {
04833         elapsed_start = edt_timestamp();
04834     }
04835 
04836     return edt_timestamp() - elapsed_start;
04837 }
04838 
04847 void
04848 edt_msleep(int msecs)
04849 {
04850 #ifdef _NT_
04851     Sleep(msecs);
04852 #elif defined(__hpux)
04853     /* hp can only handle if usleep < 1000000 */
04854     if (msecs > 1000)
04855     {
04856         sleep(msecs / 1000) ;
04857     }
04858     else
04859         usleep(msecs * 1000);
04860 #elif defined(VXWORKS)
04861 
04862 #if defined(VMIC) || defined(AV3_BOARD) || defined (cct310) || defined(XCALIBURCOMMON)
04863     taskDelay((msecs * sysClkRateGet()) / 1000) ;
04864 #elif defined(RADSTONE)
04865     /* nanosleep(msecs * 1000);*/
04866     sysStallExecution(msecs*1000) ;
04867 #else
04868     sysMsDelay(msecs) ;
04869 #endif
04870 
04871 #elif defined(__sun) || defined(__linux__)
04872 #pragma weak nanosleep
04873 
04874     {
04875         int nanoflag = (int) nanosleep;
04876 
04877         if (nanoflag)
04878         {
04879             struct timespec ts;
04880             double farg = (double)msecs;
04881 
04882             ts.tv_sec = (time_t) ((farg * 1000000.0) / 1000000000.0);
04883             ts.tv_nsec = (long) (msecs % 1000) * 1000000;
04884 
04885             (void)nanosleep(&ts, NULL);
04886         }
04887         else
04888             usleep(msecs * 1000);
04889     }
04890 #elif defined(__APPLE__)
04891     usleep(msecs * 1000);
04892 #endif
04893 }
04894 
04895 
04903 void
04904 edt_usleep(int usecs)
04905 {
04906     edt_msg(EDTDEBUG, "edt_usleep(%d)\n", usecs);
04907 #ifdef _NT_
04908     Sleep(usecs/1000);
04909 #elif defined(__hpux)
04910     /* hp can only handle if usleep < 1000000 */
04911     if (usecs > 1000000)
04912     {
04913         sleep(usecs / 1000000) ;
04914     }
04915     else
04916         usleep(usecs);
04917 #elif defined(VXWORKS)
04918 
04919 #if defined(VMIC) || defined(AV3_BOARD) || defined (cct310)
04920     taskDelay((usecs * sysClkRateGet()) / 1000000) ;
04921 #elif defined(RADSTONE)
04922     /* nanosleep(usecs);*/
04923     sysStallExecution(usecs) ;
04924 #else
04925     sysMsDelay(usecs) ;
04926 #endif
04927 
04928 #elif defined(__sun) || defined(__linux__)
04929 #pragma weak nanosleep
04930 
04931     {
04932         int nanoflag = (int) nanosleep;
04933 
04934         if (nanoflag)
04935         {
04936             struct timespec ts;
04937 
04938             ts.tv_sec = usecs / 1000000;
04939             ts.tv_nsec = (long) (usecs % 1000000) * 1000;
04940 
04941             (void)nanosleep(&ts, NULL);
04942         }
04943         else
04944             usleep(usecs);
04945     }
04946 #endif
04947 }
04948 
04949 void
04950 edt_usec_busywait(u_int usec)
04951 {
04952     double t = 0.0, f_usec = usec / 1000000;
04953 
04954     edt_dtime();           /* edt_dtime() returns a double containing the delta time since last called. */
04955     while (t < f_usec)
04956         t += edt_dtime();  /* spin until the sum of the deltas equals the input. */
04957 }
04958 
04959 void
04960 edt_check_foi(EdtDev * edt_p)
04961 {
04962     int     retval = 0;
04963     char    msgbuf[256];
04964     int     foicount;
04965     int     loop = 0;
04966 
04967     if (edt_p->devid == PDVFOI_ID)
04968     {
04969         int     count = edt_get_foicount(edt_p);
04970 
04971         if (count)
04972         {
04973             edt_msg(EDTDEBUG, "foi_count %d cur unit %d\n", count, edt_p->foi_unit);
04974         }
04975         else while (retval == 0)
04976         {
04977             char   *tmpp = msgbuf;
04978 
04979             if (loop)
04980                 edt_msleep(1000);
04981 
04982             edt_msg(EDTDEBUG, "foi count 0 - doing autoconfig\n");
04983             edt_reset_serial(edt_p);
04984             edt_init_mac8100(edt_p);
04985             edt_msleep(100);
04986 #if 1
04987             /* for now -  to flush full mac8101 receive fifo on pcifoi mac8100 hw reset */
04988             /*  - send to unit 14 so no response */
04989             edt_send_msg(edt_p, 0x2e, "b", 1);
04990             edt_serial_wait(edt_p, 100, 0) ;
04991             edt_msleep(100);
04992 #endif
04993             edt_send_msg(edt_p, 0x3f, "A", 1);
04994             edt_serial_wait(edt_p, 100, 0) ;
04995             /*
04996             * give rci time to turn off passthru (~1ms)
04997             */
04998             edt_msleep(100);
04999             /* assign first rci in path as unit 0 */
05000             edt_send_msg(edt_p, 0x3f, "U 0", 3);
05001             edt_serial_wait(edt_p, 100, 0) ;
05002             retval = 0;
05003             foicount = 0;
05004             edt_msleep(1000);
05005             /* default to 0 */
05006             edt_set_foiunit(edt_p, 0);
05007 
05008             edt_msleep(100);
05009             retval = edt_get_msg(edt_p, msgbuf, sizeof(msgbuf));
05010             if (retval != 0)
05011             {
05012                 while (tmpp < &tmpp[retval - 4])
05013                 {
05014                     edt_msg(EDTDEBUG, "string <%s>\n", tmpp);
05015                     if (tmpp[0] == 0x3f && tmpp[1] == 'U' && tmpp[2] == ' ')
05016                     {
05017                         foicount = atoi(&tmpp[3]);
05018                         edt_msg(EDTDEBUG, "setting foi count to %d\n", foicount);
05019                         edt_set_foicount(edt_p, foicount);
05020                         break;
05021                     }
05022                     tmpp++;
05023                 }
05024             }
05025             if (loop++ > 3)
05026             {
05027                 edt_msg(EDTDEBUG, "leaving checkfoi without response\n");
05028                 return;
05029             }
05030             edt_msleep(1000);
05031 
05032             edt_msg(EDTDEBUG, "done with auto config\n");
05033             edt_send_msg(edt_p, 0, "i", 1);
05034             edt_msleep(100);
05035             edt_get_msg(edt_p, msgbuf, sizeof(msgbuf));
05036             edt_send_msg(edt_p, 0, "z", 1);
05037             edt_msleep(100);
05038             edt_get_msg(edt_p, msgbuf, sizeof(msgbuf));
05039             edt_msg(EDTDEBUG, "done with init and flush\n");
05040         }
05041     }
05042 }
05043 
05044 int
05045 edt_set_statsig(EdtDev * edt_p, int event, int sig)
05046 {
05047     edt_buf buf;
05048 
05049     buf.desc = event;
05050     buf.value = sig;
05051     return (edt_ioctl(edt_p, EDTS_EVENT_SIG, &buf));
05052 }
05053 
05054 int
05055 edt_set_eodma_int(EdtDev * edt_p, int sig)
05056 {
05057     return (edt_ioctl(edt_p, EDTS_EODMA_SIG, &sig));
05058 }
05059 
05060 int
05061 edt_set_autodir(EdtDev * edt_p, int val)
05062 {
05063     return (edt_ioctl(edt_p, EDTS_AUTODIR, &val));
05064 }
05065 
05085 int
05086 edt_set_firstflush(EdtDev * edt_p, int flag)
05087 {
05088     return (edt_ioctl(edt_p, EDTS_FIRSTFLUSH, &flag));
05089 }
05090 
05091 
05115 int
05116 edt_get_firstflush(EdtDev * edt_p)
05117 {
05118 
05119     int val;
05120 
05121     edt_ioctl(edt_p, EDTG_FIRSTFLUSH, &val);
05122 
05123     return val;
05124 }
05125 
05126 
05127 u_char
05128 edt_set_funct_bit(EdtDev * edt_p, u_char mask)
05129 {
05130     unsigned char funct;
05131 
05132     funct = edt_reg_read(edt_p, PCD_FUNCT);
05133     funct |= mask;
05134     edt_reg_write(edt_p, PCD_FUNCT, funct);
05135     return (funct);
05136 }
05137 
05138 u_char
05139 edt_clr_funct_bit(EdtDev * edt_p, u_char mask)
05140 {
05141     u_char  funct;
05142 
05143     funct = edt_reg_read(edt_p, PCD_FUNCT);
05144     funct &= ~mask;
05145     edt_reg_write(edt_p, PCD_FUNCT, funct);
05146     return (funct);
05147 }
05148 
05149 
05154 static void
05155 shft_av9110(EdtDev * edt_p, u_int data, u_int numbits)
05156 {
05157     int use_pcd_method;
05158 
05159     if (ID_IS_PCD(edt_p->devid) || edt_p->devid == PDVAERO_ID)
05160         use_pcd_method = 1;
05161     else
05162         use_pcd_method = 0;
05163 
05164     while (numbits)
05165     {
05166         if (use_pcd_method)
05167         {
05168             if (data & 0x1)
05169                 edt_set_funct_bit(edt_p, EDT_FUNCT_DATA);
05170             else
05171                 edt_clr_funct_bit(edt_p, EDT_FUNCT_DATA);
05172             /* clock it in */
05173             edt_set_funct_bit(edt_p, EDT_FUNCT_CLK);
05174             edt_clr_funct_bit(edt_p, EDT_FUNCT_CLK);
05175         }
05176         else
05177         {
05178             if (data & 0x1)
05179                 edt_set_pllct_bit(edt_p, EDT_FUNCT_DATA);
05180             else
05181                 edt_clr_pllct_bit(edt_p, EDT_FUNCT_DATA);
05182             /* clock it in */
05183             edt_set_pllct_bit(edt_p, EDT_FUNCT_CLK);
05184             edt_clr_pllct_bit(edt_p, EDT_FUNCT_CLK);
05185 
05186         }
05187         data = data >> 1;
05188         numbits--;
05189     }
05190 }
05191 
05192 u_char
05193 edt_set_pllct_bit(EdtDev * edt_p, u_char mask)
05194 {
05195     unsigned char pll_ct;
05196 
05197     pll_ct = edt_reg_read(edt_p, PDV_PLL_CTL);
05198     pll_ct |= mask;
05199     edt_reg_write(edt_p, PDV_PLL_CTL, pll_ct);
05200     return (pll_ct);
05201 }
05202 
05203 u_char
05204 edt_clr_pllct_bit(EdtDev * edt_p, u_char mask)
05205 {
05206     u_char  pll_ct;
05207 
05208     pll_ct = edt_reg_read(edt_p, PDV_PLL_CTL);
05209     pll_ct &= ~mask;
05210     edt_reg_write(edt_p, PDV_PLL_CTL, pll_ct);
05211     return (pll_ct);
05212 }
05213 
05214 void
05215 edt_set_out_clk(EdtDev * edt_p, edt_pll * clk_data)
05216 {
05217     int use_pcd_method;
05218 
05219     unsigned char opt_e = 0;
05220     u_int   svfnct;
05221 
05222     if (ID_IS_PCD(edt_p->devid) || edt_p->devid == PDVAERO_ID)
05223         use_pcd_method = 1;
05224     else
05225         use_pcd_method = 0;
05226 
05227     switch (clk_data->h)
05228     {
05229     case 1:
05230         opt_e = EDT_FAST_DIV1;
05231         break;
05232 
05233     case 3:
05234         opt_e = EDT_FAST_DIV3;
05235         break;
05236 
05237     case 5:
05238         opt_e = EDT_FAST_DIV5;
05239         break;
05240 
05241     case 7:
05242         opt_e = EDT_FAST_DIV7;
05243         break;
05244 
05245     default:
05246         edt_msg(EDTDEBUG, "Illegal value %d for xilinx fast clk divide\n",
05247             clk_data->h);
05248         opt_e = EDT_FAST_DIV1;
05249         clk_data->h = 1;
05250         break;
05251     }
05252     opt_e |= ((clk_data->l - 1) << EDT_X_DIVN_SHFT);
05253 
05254 
05255     if (use_pcd_method)
05256     {
05257         edt_reg_write(edt_p, EDT_OUT_SCALE, opt_e);
05258         edt_reg_write(edt_p, EDT_REF_SCALE, clk_data->x - 1);
05259         svfnct = edt_reg_read(edt_p, PCD_FUNCT);
05260         edt_set_funct_bit(edt_p, EDT_FUNCT_SELAV);
05261         edt_clr_funct_bit(edt_p, EDT_FUNCT_CLK);
05262 
05263 
05264     }
05265     else
05266     {
05267         edt_reg_write(edt_p, PDV_OUT_SCALE, opt_e);
05268         edt_reg_write(edt_p, PDV_REF_SCALE, clk_data->x - 1);
05269         svfnct = edt_reg_read(edt_p, PDV_PLL_CTL);
05270         edt_set_pllct_bit(edt_p, EDT_FUNCT_SELAV);
05271         edt_clr_pllct_bit(edt_p, EDT_FUNCT_CLK);
05272 
05273     }
05274 
05275 
05276     svfnct &= ~EDT_FUNCT_SELAV;  /* Must turn this off when done - jerry */
05277 
05278     /* shift out data */
05279     shft_av9110(edt_p, clk_data->n, 7);
05280     shft_av9110(edt_p, clk_data->m, 7);
05281     /* set vco preescale */
05282     if (clk_data->v == 1)
05283         shft_av9110(edt_p, 0, 1);
05284     else
05285         shft_av9110(edt_p, 1, 1);
05286     /* clkx divide is not used (right now) so set to div 1 */
05287     switch (clk_data->r)
05288     {
05289     case 1:
05290         shft_av9110(edt_p, 0x170, 9);
05291         break;
05292 
05293     case 2:
05294         shft_av9110(edt_p, 0x174, 9);
05295         break;
05296 
05297     case 4:
05298         shft_av9110(edt_p, 0x178, 9);
05299         break;
05300 
05301     case 8:
05302         shft_av9110(edt_p, 0x17c, 9);
05303         break;
05304 
05305     default:
05306         edt_msg(EDTDEBUG, "illegal value %d for AV9110 aoutput divide\n",
05307             clk_data->r);
05308         shft_av9110(edt_p, 0x5c, 7);
05309         break;
05310     }
05311     /* restore fnct bits */
05312 
05313     if (use_pcd_method)
05314         edt_reg_write(edt_p, PCD_FUNCT, svfnct);
05315     else
05316         edt_reg_write(edt_p, PDV_PLL_CTL, svfnct);
05317 
05318 }
05319 
05320 u_int
05321 edt_set_sglist(EdtDev *edt_p, 
05322                uint_t bufnum, 
05323                uint_t *log_list,
05324                uint_t log_entrys)
05325 {
05326     int ret ;
05327     buf_args sg_args ;
05328     sg_args.index = bufnum ;
05329     sg_args.size = log_entrys ;
05330 #ifdef WIN32
05331     sg_args.addr = (uint64_t) (log_list);
05332 #else
05333     sg_args.addr = (uint64_t) ((unsigned long) log_list);
05334 #endif
05335     ret = edt_ioctl(edt_p, EDTS_SGLIST, &sg_args);
05336 
05337     return ret;
05338 }
05339 
05340 u_int
05341 edt_set_sgbuf(EdtDev * edt_p, u_int sgbuf, u_int bufsize, u_int bufdir, u_int verbose)
05342 {
05343     edt_set_buffer_size(edt_p, sgbuf, bufsize, bufdir) ;
05344     return 0;
05345 }
05346 
05363 int
05364 edt_set_timeout_action(EdtDev * edt_p, u_int action)
05365 
05366 {
05367 
05368     if (!edt_p)
05369     {
05370         return -1;
05371 
05372     }
05373 
05374     edt_ioctl(edt_p, EDTS_TIMEOUT_ACTION, &action);
05375 
05376     return 0;
05377 }
05378 
05392 int
05393 edt_get_timeout_goodbits(EdtDev * edt_p)
05394 
05395 {
05396 
05397     u_int   nGoodBits;
05398 
05399     if (!edt_p)
05400     {
05401         return 0;
05402     }
05403 
05404     edt_ioctl(edt_p, EDTG_TIMEOUT_GOODBITS, &nGoodBits);
05405 
05406     return nGoodBits;
05407 }
05408 
05422 int
05423 edt_get_goodbits(EdtDev * edt_p)
05424 
05425 {
05426 
05427     u_int   nGoodBits;
05428 
05429     if (!edt_p)
05430     {
05431         return 0;
05432     }
05433 
05434     edt_ioctl(edt_p, EDTG_GOODBITS, &nGoodBits);
05435 
05436     return nGoodBits;
05437 }
05438 
05543 #ifdef _NT_
05544 
05545 int
05546 edt_get_kernel_event(EdtDev *edt_p, int event_type)
05547 
05548 {
05549     EdtEventHandler *p;
05550     char    fullname[128];
05551     char   *Name;
05552     char *edt_devname;
05553 
05554     if (edt_p == NULL 
05555         || (event_type < 0)
05556         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05557         || ((Name = BaseEventNames[event_type]) == NULL)
05558         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05559     {
05560         /* out of range */
05561         edt_msg(EDTDEBUG, "Invalid argument to edt_get_kernel_event\n");
05562         return -1;
05563     }
05564 
05565     switch(edt_p->devid)
05566     {
05567     case P11W_ID:
05568         edt_devname = "P11w";
05569         break;
05570 
05571     case P16D_ID:
05572         edt_devname = "P16d";
05573         break;
05574 
05575     case PCD20_ID:
05576     case PCD40_ID:
05577     case PCD60_ID:
05578     case PCD_16_ID:
05579     case PGP20_ID:
05580     case PGP40_ID:
05581     case PGP60_ID:
05582     case PGP_ECL_ID:
05583     case PSS4_ID:
05584     case PSS16_ID:
05585     case PGS4_ID:
05586     case PGS16_ID:
05587     case PCDA_ID:
05588     case PCDCL_ID:
05589     case PCDA16_ID:
05590     case PCDFCI_SIM_ID:
05591     case PCDFCI_PCD_ID:
05592     case PCDFOX_ID:
05593     case PE8LX1_ID:
05594     case PE8LX4_ID:
05595     case PE8LX16_ID:
05596         edt_devname = "Pcd";
05597         break;
05598 
05599     case PDV_ID:
05600     case PDVA_ID:
05601     case PDVA16_ID:
05602     case PGP_RGB_ID:
05603     case PDVK_ID:
05604     case PDVCL_ID:
05605     case PDVCL2_ID:
05606     case PE4DVCL_ID:
05607     case PE4DVFOX_ID:
05608     case PE8DVCL_ID:
05609     case PE8DVFOX_ID:
05610     case PDV44_ID:
05611     case PDVFOI_ID:
05612     case PDVFCI_AIAG_ID:
05613     case PDVFCI_USPS_ID:
05614     case PDVFOX_ID:
05615     case PDVAERO_ID:
05616         edt_devname = "Pdv";
05617         break;
05618 
05619     case P53B_ID:
05620         edt_devname = "P53b";
05621         break;
05622 
05623     default:
05624         edt_devname = NULL;
05625         edt_msg(EDTDEBUG, "Unknown device type %d\n", edt_p->devid);
05626         return -1;
05627 
05628     }
05629 
05630     sprintf(fullname, "%s%s%d%d", edt_devname, Name, edt_p->unit_no, edt_p->channel_no);
05631 
05632     if ((p->wait_event =
05633         CreateEvent(NULL, FALSE, FALSE,fullname)) == NULL)
05634     {
05635         if ((p->wait_event =
05636             OpenEvent(SYNCHRONIZE, FALSE, fullname)) == NULL)
05637         {
05638 
05639             edt_msg(EDTDEBUG, "Unable to open event %s\n", fullname);
05640             edt_msg_perror(EDTFATAL, "event") ;
05641 
05642             return -1;
05643 
05644         }
05645         else
05646         {
05647             ResetEvent(p->wait_event) ;
05648             return(0) ;
05649         }
05650 
05651     }
05652     else
05653     {
05654         edt_buf argbuf ;
05655         argbuf.desc = event_type ;
05656         argbuf.value = (uint64_t)p->wait_event ;
05657         edt_ioctl(edt_p, EDTS_EVENT_HNDL, &argbuf);
05658         ResetEvent(p->wait_event) ;
05659     }
05660 
05661     return 0;
05662 
05663 }
05664 
05665 /********************************************************
05666 * Close everything and zero memory
05667 ********************************************************/
05668 
05669 static
05670 void
05671 edt_clear_event_func(EdtEventHandler * p)
05672 
05673 {
05674     if (p->wait_thread)
05675         CloseHandle(p->wait_thread);
05676     if (p->wait_event)
05677         CloseHandle(p->wait_event);
05678     if (p->closing_event)
05679         CloseHandle(p->closing_event);
05680 
05681     memset(p, 0, sizeof(*p));
05682 
05683 }
05684 
05685 /********************************************************/
05686 /* Thread function to wait on a particular driver event */
05687 /********************************************************/
05688 
05689 static u_int WINAPI
05690 edt_wait_event_thread(void *pObj)
05691 {
05692     EdtEventHandler *p = (EdtEventHandler *) pObj;
05693     int     rc = WAIT_OBJECT_0;
05694     HANDLE  events[2];
05695     u_int   tmp;
05696 
05697 
05698     if (p)
05699     {
05700         events[0] = p->wait_event;
05701         events[1] = p->closing_event;
05702 
05703         while (p->active)
05704         {
05705 
05706 #ifndef NEW_WAY
05707             rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
05708 #else
05709 
05710             edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
05711 #endif
05712 
05713             if (p->active && rc == WAIT_OBJECT_0)
05714             {
05715                 edt_ioctl(p->owner, EDTS_CLR_EVENT, &p->event_type);
05716 
05717                 if (p->callback)
05718                     p->callback(p->data);
05719 
05720             }
05721 
05722             if (p->continuous == 0)
05723             {
05724                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
05725 
05726                 /* May need this later -- Mark 01/99 */
05727                 tmp = p->thrdid;
05728                 /*p->active = 0 ;*/
05729                 edt_clear_event_func(p);
05730                 p->thrdid = tmp;
05731 
05732                 break;
05733             }
05734         }
05735     }
05736     return 0;
05737 }
05738 
05739 /* ****************************************************** */
05740 /* Add an event function for an event_type               */
05741 /* Name is derived from event type -                     */
05742 /* only works for "base events" defined for all boards   */
05743 /* ****************************************************** */
05744 
05745 int
05746 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc func, void *data,
05747                    int continuous)
05748 {
05749     EdtEventHandler *p;
05750     char   *Name;
05751     HANDLE event;
05752 
05753     edt_msg(EDTDEBUG, "edt_set_event_func(type %d cont %d)\n", event_type, continuous);
05754 
05755     if (edt_p == NULL || (func == NULL)
05756         || (event_type < 0)
05757         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05758         || ((Name = BaseEventNames[event_type]) == NULL)
05759         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05760     {
05761         /* out of range */
05762         return -1;
05763     }
05764 
05765 
05766     if (p->callback)
05767     {
05768         /* whoops - we're already going */
05769 
05770         /* if it's the same callback, no problem */
05771 
05772         if (p->callback == func && p->data == data)
05773             return 0;
05774         else
05775             return -1;
05776     }
05777 
05778     /* Set the function */
05779     p->callback = func;
05780     /* Set the data */
05781     p->data = data;
05782 
05783     p->owner = edt_p;
05784     p->active = TRUE;
05785     p->event_type = event_type;
05786     p->continuous = continuous;
05787 
05788 
05789     /* Unlock */
05790 
05791     /* Launch the thread */
05792 
05793 
05794     edt_get_kernel_event(edt_p, event_type) ;
05795     event = edt_p->event_funcs[event_type].wait_event;
05796 
05797     if (event == NULL)
05798     {
05799         edt_clear_event_func(p);
05800         return -1;
05801 
05802     }
05803 
05804     if ((p->closing_event = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
05805     {
05806         edt_clear_event_func(p);
05807         return -1;
05808     }
05809 
05810     if ((p->wait_thread = (thread_t)
05811         _beginthreadex(NULL, 0, edt_wait_event_thread, p, CREATE_SUSPENDED,
05812         &p->thrdid)) == NULL)
05813     {
05814         edt_clear_event_func(p);
05815         return -1;
05816     }
05817 
05818     /*
05819     * The continuous parameter now supports one of three modes:
05820     *
05821     *           EDT_EVENT_MODE_ONCE             (0)
05822     *           EDT_EVENT_MODE_CONTINUOUS       (1)
05823     *           EDT_EVENT_MODE_SERIALIZE        (2)
05824     *
05825     * The mode is passed to the driver in the high byte of event_type.
05826     */
05827     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
05828     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05829     event_type &= ~EDT_EVENT_MODE_MASK ;
05830 
05831     ResumeThread(p->wait_thread);
05832 
05833     /*SetThreadPriority(p->wait_thread, THREAD_PRIORITY_HIGHEST);*/
05834 
05835     return 0;
05836 }
05837 
05838 int
05839 edt_remove_event_func(EdtDev * edt_p, int event_type)
05840 
05841 {
05842     EdtEventHandler *p;
05843 
05844     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
05845     {
05846         /* out of range */
05847         return -1;
05848     }
05849 
05850     p = &edt_p->event_funcs[event_type];
05851 
05852     /*
05853     * Try and close the thread gracefully
05854     */
05855 
05856     if (p->wait_thread && p->wait_event)
05857     {
05858         p->active = FALSE;
05859 
05860         SetEvent(p->closing_event);
05861 
05862         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
05863 
05864         WaitForSingleObject(p->wait_thread, INFINITE);
05865 
05866         edt_clear_event_func(p);
05867 
05868     }else
05869         edt_clear_event_func(p);
05870 
05871     return 0;
05872 }
05873 
05874 #elif defined(__sun)            /* _NT_ */
05875 
05876 /* *******************************************************/
05877 /* Add an event function for an event_type               */
05878 /* Name is derived from event type                       */
05879 /* - only works for "base events" defined for all boards */
05880 /* *******************************************************/
05881 
05882 int
05883 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
05884                    int continuous)
05885 {
05886     EdtEventHandler *p;
05887     char    fullname[128];
05888     char   *Name;
05889 
05890 
05891     if (edt_p == NULL || (f == NULL)
05892         || (event_type < 0)
05893         || (event_type >= EDT_MAX_KERNEL_EVENTS)
05894         || ((Name = BaseEventNames[event_type]) == NULL)
05895         || ((p = &edt_p->event_funcs[event_type]) == NULL))
05896     {
05897         /* out of range */
05898         return -1;
05899     }
05900 
05901     if (p->active && p->callback)
05902     {
05903         /* whoops - we're already going */
05904         edt_remove_event_func(edt_p, event_type);
05905     }
05906     /*
05907     * Solaris:  if another thread has run for this event, wait for it.
05908     * Otherwise it stays alive and uses mmap() resources.  Mark  01/99
05909     */
05910     else if (p->thrdid)
05911         thr_join(p->thrdid, NULL, NULL);
05912 
05913     /* Set the function */
05914     p->callback = f;
05915     /* Set the data */
05916     p->data = data;
05917 
05918     p->owner = edt_p;
05919     p->active = TRUE;
05920     p->event_type = event_type;
05921     p->continuous = continuous;
05922 
05923     sema_init(&p->sema_thread, 0, USYNC_PROCESS, NULL);
05924 
05925     /*
05926     * The continuous parameter now supports one of three modes:
05927     *
05928     *           EDT_EVENT_MODE_ONCE             (0)
05929     *           EDT_EVENT_MODE_CONTINUOUS       (1)
05930     *           EDT_EVENT_MODE_SERIALIZE        (2)
05931     *
05932     * The mode is passed to the driver in the high byte of event_type.
05933     */
05934     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
05935     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
05936     event_type &= ~EDT_EVENT_MODE_MASK ;
05937 
05938     /* Launch the thread */
05939 
05940     sprintf(fullname, "%s%d%d", Name, edt_p->unit_no, edt_p->channel_no);
05941     if (thr_create(NULL, 0, edt_wait_event_thread, (void *) p,
05942         THR_NEW_LWP | THR_BOUND, &p->thrdid))
05943     {
05944         edt_msg_perror(EDTFATAL, "edt_set_event_func: thr_create");
05945         edt_msg(EDTWARN, "Unable to create eventthread %s\n", fullname);
05946         edt_msg(EDTWARN, "thr_create:  use \"-lthread\" compile option\n", stderr);
05947         return -1;
05948     }
05949 
05950     sema_wait(&p->sema_thread);
05951     thr_yield();
05952 
05953     return 0;
05954 }
05955 
05956 /********************************************************/
05957 /* Close everything and zero memory                      */
05958 /********************************************************/
05959 
05960 static
05961 void
05962 edt_clear_event_func(EdtEventHandler * p)
05963 
05964 {
05965     /* TODO - anything else need to be done here for solaris?  -- Mark 01/99 */
05966     memset(p, 0, sizeof(*p));
05967 }
05968 
05969 
05970 /********************************************************/
05971 /* Thread function to wait on a particular driver event */
05972 /********************************************************/
05973 
05974 static void *
05975 edt_wait_event_thread(void *pObj)
05976 
05977 {
05978     EdtEventHandler *p = (EdtEventHandler *) pObj;
05979     thread_t tmp;
05980     int     ret;
05981 
05982 #ifdef __sun
05983     if (p->owner->use_RT_for_event_func)
05984         edt_set_RT(1) ;         /* This isn't a good idea unless
05985                                 * you really can't live without it.  - Mark
05986                                 */
05987 #endif
05988 
05989     if (p)
05990     {
05991         while (p->active)
05992         {
05993             sema_post(&p->sema_thread);
05994             if (p->continuous == 0)
05995                 edt_ioctl(p->owner, EDTS_WAIT_EVENT_ONCE, &p->event_type);
05996             else
05997                 edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
05998 
05999             if (p->active && p->callback)
06000                 p->callback(p->data);
06001 
06002             if (p->continuous == 0)
06003             {
06004                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
06005 
06006                 /* Need this later for thr_join() in set_event_func() */
06007                 tmp = p->thrdid;
06008                 edt_clear_event_func(p);
06009                 p->thrdid = tmp;
06010 
06011                 break;
06012             }
06013         }
06014     }
06015 
06016     thr_exit(NULL);
06017 
06018     return pObj;
06019 }
06020 
06021 /* *******************************************************/
06022 /* Delete an event handler                               */
06023 /* *******************************************************/
06024 
06025 int
06026 edt_remove_event_func(EdtDev * edt_p, int event_type)
06027 {
06028     EdtEventHandler *p;
06029 
06030     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
06031     {
06032         /* out of range */
06033         return -1;
06034     }
06035 
06036     p = &edt_p->event_funcs[event_type];
06037 
06038     /*
06039     * Try and close the thread gracefully
06040     */
06041 
06042     if (p->active)
06043     {
06044         p->active = FALSE;
06045 
06046         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
06047 
06048         thr_join(p->thrdid, NULL, NULL);
06049 
06050         edt_clear_event_func(p);
06051     }
06052 
06053     return 0;
06054 }
06055 #elif defined(sgi) || defined(__linux__) || defined(__APPLE__)
06056 
06057 #ifndef NO_PTHREAD
06058 
06059 #include <pthread.h>
06060 
06061 /* *******************************************************/
06062 /* Add an event function for an event_type               */
06063 /* Name is derived from event type                       */
06064 /* - only works for "base events" defined for all boards */
06065 /* *******************************************************/
06066 
06067 int
06068 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
06069                    int continuous)
06070 {
06071     EdtEventHandler *p;
06072     char    fullname[128];
06073     char   *Name;
06074 
06075 
06076     if (edt_p == NULL || (f == NULL)
06077         || (event_type < 0)
06078         || (event_type >= EDT_MAX_KERNEL_EVENTS)
06079         || ((Name = BaseEventNames[event_type]) == NULL)
06080         || ((p = &edt_p->event_funcs[event_type]) == NULL))
06081     {
06082         /* out of range */
06083         return -1;
06084     }
06085 
06086     if (p->active && p->callback)
06087     {
06088         /* whoops - we're already going */
06089         edt_remove_event_func(edt_p, event_type);
06090     }
06091     /*
06092     * pthreads:  if another thread has run for this event, wait for it.
06093     * Otherwise it stays alive and uses mmap() resources.  Mark  01/99
06094     */
06095     else if (p->thrdid)
06096         pthread_join(p->thrdid, NULL);
06097 
06098     /* Set the function */
06099     p->callback = f;
06100     /* Set the data */
06101     p->data = data;
06102 
06103     p->owner = edt_p;
06104     p->active = TRUE;
06105     p->event_type = event_type;
06106     p->continuous = continuous;
06107 
06108 
06109     /* sema_init(&p->sema_thread, 0, USYNC_PROCESS, NULL); */
06110 
06111     /*
06112     * The continuous parameter now supports one of three modes:
06113     *
06114     *           EDT_EVENT_MODE_ONCE             (0)
06115     *           EDT_EVENT_MODE_CONTINUOUS       (1)
06116     *           EDT_EVENT_MODE_SERIALIZE        (2)
06117     *
06118     * The mode is passed to the driver in the high byte of event_type.
06119     */
06120     event_type |= ((continuous << EDT_EVENT_MODE_SHFT) & EDT_EVENT_MODE_MASK) ;
06121     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
06122     event_type &= ~EDT_EVENT_MODE_MASK ;
06123 
06124     /* Launch the thread */
06125 
06126     sprintf(fullname, "%s%d%d", Name, edt_p->unit_no, edt_p->channel_no);
06127     if (pthread_create(&p->thrdid, 0, edt_wait_event_thread, (void *) p)
06128         != 0)
06129     {
06130         edt_msg_perror(EDTFATAL, "edt_set_event_func: thr_create");
06131         edt_msg(EDTWARN, "Unable to create eventthread %s\n", fullname);
06132         edt_msg(EDTWARN, "thr_create:  use \"-lthread\" compile option\n", stderr);
06133         return -1;
06134     }
06135 
06136     /* sema_wait(&p->sema_thread); */
06137     /* thr_yield(); */
06138 
06139     return 0;
06140 }
06141 
06142 /********************************************************/
06143 /* Close everything and zero memory                      */
06144 /********************************************************/
06145 
06146 static
06147 void
06148 edt_clear_event_func(EdtEventHandler * p)
06149 
06150 {
06151     /* TODO - anything else need to be done here for solaris?  -- Mark 01/99 */
06152     memset(p, 0, sizeof(*p));
06153 }
06154 
06155 
06156 /********************************************************/
06157 /* Thread function to wait on a particular driver event */
06158 /********************************************************/
06159 
06160 static void *
06161 edt_wait_event_thread(void *pObj)
06162 
06163 {
06164     EdtEventHandler *p = (EdtEventHandler *) pObj;
06165     pthread_t tmp;
06166 
06167     if (p)
06168     {
06169         while (p->active)
06170         {
06171             /* sema_post(&p->sema_thread); */
06172             if (p->continuous == 0)
06173                 edt_ioctl(p->owner, EDTS_WAIT_EVENT_ONCE, &p->event_type);
06174             else
06175                 edt_ioctl(p->owner, EDTS_WAIT_EVENT, &p->event_type);
06176 
06177             if (p->active && p->callback)
06178                 p->callback(p->data);
06179 
06180             if (p->continuous == 0)
06181             {
06182                 edt_ioctl(p->owner, EDTS_DEL_EVENT_FUNC, &p->event_type);
06183 
06184                 /* Need this later for thr_join() in set_event_func() */
06185                 tmp = p->thrdid;
06186                 edt_clear_event_func(p);
06187                 p->thrdid = tmp;
06188 
06189                 break;
06190             }
06191         }
06192     }
06193 
06194     pthread_exit(NULL);
06195 
06196     return pObj;
06197 }
06198 
06199 /* *******************************************************/
06200 /* Delete an event handler                               */
06201 /* *******************************************************/
06202 
06203 int
06204 edt_remove_event_func(EdtDev * edt_p, int event_type)
06205 {
06206     EdtEventHandler *p;
06207 
06208     if (edt_p == NULL || event_type < 0 || event_type >= EDT_MAX_KERNEL_EVENTS)
06209     {
06210         /* out of range */
06211         return -1;
06212     }
06213 
06214     p = &edt_p->event_funcs[event_type];
06215 
06216     /*
06217     * Try and close the thread gracefully
06218     */
06219 
06220     if (p->active)
06221     {
06222         p->active = FALSE;
06223 
06224         edt_ioctl(edt_p, EDTS_DEL_EVENT_FUNC, &event_type);
06225 
06226         pthread_join(p->thrdid, NULL);
06227 
06228         edt_clear_event_func(p);
06229     }
06230 
06231     return 0;
06232 }
06233 #endif   /* NOT PTHREAD */
06234 
06235 #elif defined(_AIX) || defined(__hpux)
06236 
06237 /* *******************************************************
06238 * Add an event function for an event_type
06239 * Name is derived from event type - only works
06240 * for "base events" defined for all boards
06241 * *******************************************************/
06242 
06243 int
06244 edt_set_event_func(EdtDev * edt_p, int event_type, EdtEventFunc f, void *data,
06245                    int continuous)
06246 {
06247     return -1;
06248 }
06249 
06250 /********************************************************
06251 * Close everything and zero memory
06252 ********************************************************/
06253 
06254 static
06255 void
06256 edt_clear_event_func(EdtEventHandler * p)
06257 
06258 {
06259 
06260 }
06261 
06262 
06263 /********************************************************
06264 * Thread function to wait on a particular driver event *
06265 ********************************************************/
06266 
06267 static void *
06268 edt_wait_event_thread(void *pObj)
06269 
06270 {
06271     return NULL;
06272 }
06273 
06274 /* *******************************************************
06275 * Delete an event handler                                                               *
06276 * *******************************************************/
06277 
06278 int
06279 edt_remove_event_func(EdtDev * edt_p, int event_type)
06280 {
06281     return -1;
06282 }
06283 
06284 #else
06285 
06286 int
06287 edt_remove_event_func(EdtDev * edt_p, int event_type)
06288 {
06289     return -1;
06290 }
06291 
06292 #endif                          /* _NT_ */
06293 
06294 int
06295 edt_enable_event(EdtDev * edt_p, int event_type)
06296 {
06297     edt_msg(EDTDEBUG, "edt_enable_event(type %d)\n", event_type) ;
06298 
06299     if (edt_p == NULL 
06300         || (event_type < 0)
06301         || (event_type >= EDT_MAX_KERNEL_EVENTS))
06302     {
06303         /* out of range */
06304         return -1;
06305     }
06306 
06307 #ifdef _NT_
06308     edt_get_kernel_event(edt_p, event_type) ;
06309 #endif
06310 
06311     edt_ioctl(edt_p, EDTS_ADD_EVENT_FUNC, &event_type);
06312 
06313     return 0 ;
06314 }
06315 
06316 int
06317 edt_wait_event(EdtDev * edt_p, int event_type, int timeoutval)
06318 {
06319     int ret = 0 ;
06320     edt_msg(EDTDEBUG, "edt_wait_event(type %d)\n", event_type) ;
06321 #ifdef _NT_
06322     {
06323         HANDLE event;
06324         int rc;
06325 
06326         if (!edt_p->event_funcs[event_type].wait_event)
06327         {
06328             edt_get_kernel_event(edt_p, event_type);
06329         }
06330 
06331         event = edt_p->event_funcs[event_type].wait_event;
06332 
06333         /* wait for event */
06334 
06335         if (timeoutval == 0)
06336             timeoutval = INFINITE;
06337 
06338         rc = WaitForSingleObject(event, timeoutval);
06339 
06340         if (rc == WAIT_TIMEOUT)
06341         {
06342             /* edt_msg(EDTDEBUG, "timeout...\n");*/
06343 
06344             /* deal with timeout */
06345 
06346             edt_do_timeout(edt_p);
06347 
06348             ret = 1 ;
06349         }
06350     }
06351 #else
06352     edt_ioctl(edt_p, EDTS_WAIT_EVENT, &event_type);
06353 #endif
06354 
06355     edt_msg(EDTDEBUG, "edt_wait_event(type %d)\n", event_type, ret) ;
06356 
06357     return(ret) ;
06358 }
06359 
06360 
06365 int
06366 edt_reset_event_counter(EdtDev * edt_p, int event_type)
06367 {
06368     return edt_ioctl(edt_p, EDTS_RESET_EVENT_COUNTER, &event_type);
06369 }
06370 
06371 
06372 
06384 int
06385 edt_stop_buffers(EdtDev * edt_p)
06386 
06387 {
06388     unsigned int finish_current = 1;
06389 
06390     edt_msg(EDTDEBUG, "edt_stop_buffers\n");
06391     edt_ioctl(edt_p, EDTS_STOPBUF, &finish_current);
06392     return 0;
06393 }
06394 
06411 int
06412 edt_reset_ring_buffers(EdtDev * edt_p, uint_t bufnum)
06413 
06414 {
06415     bufcnt_t     curdone;
06416     int     curbuf = -1;
06417 
06418     curdone = edt_done_count(edt_p);
06419     edt_cancel_current_dma(edt_p);
06420     if (edt_p->ring_buffer_numbufs)
06421     {
06422         curbuf = curdone % edt_p->ring_buffer_numbufs;
06423         edt_set_buffer(edt_p, bufnum);
06424     }
06425     edt_msg(EDTDEBUG, "edt_reset_ring_buffers buf %d curdone %d curbuf %d\n",
06426         bufnum, curdone, curbuf);
06427     return 0;
06428 }
06429 
06443 int
06444 edt_abort_dma(EdtDev * edt_p)
06445 
06446 {
06447     edt_msg(EDTDEBUG, "edt_abort_dma\n");
06448     edt_reset_ring_buffers(edt_p, edt_done_count(edt_p));
06449     return 0;
06450 }
06451 
06465 int
06466 edt_abort_current_dma(EdtDev * edt_p)
06467 
06468 {
06469     edt_msg(EDTDEBUG, "edt_abort_current_dma\n");
06470     edt_reset_ring_buffers(edt_p, edt_done_count(edt_p) + 1);
06471     return 0;
06472 }
06473 
06484 int
06485 edt_ring_buffer_overrun(EdtDev *edt_p)
06486 
06487 {
06488     bufcnt_t   dmacount;
06489 
06490     dmacount = edt_done_count(edt_p);
06491 
06492     if (dmacount >= edt_p->donecount + edt_p->ring_buffer_numbufs)
06493         return (1);
06494     else
06495         return (0);
06496 }
06497 
06498 
06499 #ifdef P16D
06500 
06511 u_short
06512 p16d_get_command(EdtDev * edt_p)
06513 {
06514     return (edt_reg_read(edt_p, P16_COMMAND));
06515 }
06516 
06528 void
06529 p16d_set_command(EdtDev * edt_p, u_short val)
06530 {
06531     edt_reg_write(edt_p, P16_COMMAND, val);
06532 }
06533 
06544 u_short
06545 p16d_get_config(EdtDev * edt_p)
06546 {
06547     return (edt_reg_read(edt_p, P16_CONFIG));
06548 }
06549 
06561 void
06562 p16d_set_config(EdtDev * edt_p, u_short val)
06563 {
06564     edt_reg_write(edt_p, P16_CONFIG, val);
06565 }
06566 
06577 u_short
06578 p16d_get_stat(EdtDev * edt_p)
06579 {
06580     return (edt_reg_read(edt_p, P16_STATUS));
06581 }
06582 
06583 #endif                          /* P16D */
06584 
06585 
06600 int
06601 edt_parse_unit_channel(const char *instr, 
06602                        char *dev, 
06603                        const char *default_dev,
06604                        int *channel_ptr)
06605 {
06606     int     unit = -1;
06607     int         channel = -1;
06608     size_t              last;
06609 
06610     char    retdev[256];
06611     char    str[256];
06612 
06613 
06614     edt_msg(EDTDEBUG, "edt_parse_unit_channel %s dev %s default %s: ", 
06615         instr, dev, default_dev);
06616 
06617     if (default_dev)
06618         strcpy(retdev, default_dev);
06619     else
06620         strcpy(retdev, EDT_INTERFACE);
06621 
06622     strcpy(str,instr);
06623 
06624     last = strlen(str)-1;
06625 
06626     /* find the channel or unit */
06627 
06628     if (isdigit(str[last]))
06629     {
06630         while (last && isdigit(str[last]))
06631         {
06632             last--;
06633         }
06634 
06635         if (!isdigit(str[last]))
06636         {
06637             last++;
06638         }
06639 
06640         channel = atoi(str+last);
06641 
06642         if (str[0] != '/' && str[0] != '\\')
06643             str[last] = 0;
06644 
06645         if (last>0)
06646             last--;
06647 
06648         if (last && str[last] == '_')
06649         {
06650 
06651             last--;
06652 
06653             if (isdigit(str[last]))
06654             {
06655                 size_t enddigit = last;
06656                 char checkstr[80];
06657 
06658                 while (last && isdigit(str[last]))
06659                 {
06660                     last--;
06661                 }
06662 
06663                 if (!isdigit(str[last]))
06664                 {
06665                     last++;
06666                 }
06667 
06668                 strncpy(checkstr,str+last,(enddigit - last)+1);
06669 
06670                 unit = atoi(checkstr);
06671 
06672                 if (str[0] != '/' && str[0] != '\\')
06673                     str[last] = 0;
06674 
06675             }   
06676             else
06677             {
06678                 unit = channel;
06679                 channel = -1;
06680             }
06681         }
06682         else
06683         {
06684             unit = channel;
06685             channel = -1;
06686         }
06687 
06688     }
06689     else
06690         unit = 0;
06691 
06692     if (str[0])
06693         strcpy(retdev, str);
06694 
06695     strcpy(dev, retdev);
06696 
06697     if (channel_ptr && (channel != -1))
06698         *channel_ptr = channel;
06699 
06700     return (unit);
06701 }
06702 
06731 int
06732 edt_parse_unit(const char *str, char *dev, const char *default_dev)
06733 {
06734     int channel = 0;
06735 
06736     return edt_parse_unit_channel(str,dev,default_dev, &channel);
06737 
06738 
06739 }
06740 int
06741 edt_serial_wait(EdtDev * edt_p, int msecs, int count) 
06742 {
06743     edt_buf tmp;
06744     int     ret;
06745 
06746     tmp.desc = msecs;
06747     tmp.value = count;
06748     edt_ioctl(edt_p, EDTS_SERIALWAIT, &tmp);
06749     ret = (u_int) tmp.value;
06750 
06751     edt_msg(EDTDEBUG, "edt_serial_wait(%d, %d) %d\n", msecs, count, ret);
06752     return (ret);
06753 }
06754 
06788 int                        
06789 edt_ref_tmstamp(EdtDev *edt_p, u_int val)
06790 
06791 {
06792     return edt_ioctl(edt_p,EDTS_REFTMSTAMP,&val);
06793 
06794 }
06795 
06796 uint_t
06797 edt_get_bufbytecount(EdtDev * edt_p, u_int *cur_buffer)
06798 {
06799     uint_t args[2] ;
06800 
06801     if (edt_ioctl(edt_p, EDTG_BUFBYTECOUNT, &args) < 0)
06802         edt_msg_perror(EDTFATAL, "edt_ioctl(EDTG_BUFBYTECOUNT)");
06803 
06804     if (cur_buffer)
06805         *cur_buffer = args[1] ;
06806     return (args[0]);
06807 }
06808 
06809 
06810 void
06811 edt_dmasync_fordev(EdtDev *edt, int bufnum, int offset, int bytecount)
06812 {
06813     u_int args[3] ;
06814 
06815     args[0] = bufnum ;
06816     args[1] = offset ;
06817     args[2] = bytecount ;
06818 
06819     edt_ioctl(edt, EDTS_DMASYNC_FORDEV, args) ;
06820 }
06821 
06822 void
06823 edt_dmasync_forcpu(EdtDev *edt, int bufnum, int offset, int bytecount)
06824 {
06825     u_int args[3] ;
06826 
06827     args[0] = bufnum ;
06828     args[1] = offset ;
06829     args[2] = bytecount ;
06830 
06831     edt_ioctl(edt, EDTS_DMASYNC_FORCPU, args) ;
06832 }
06833 
06834 /* return true if machine is little_endian */
06835 int
06836 edt_little_endian()
06837 {
06838     u_short test;
06839     u_char *byte_p;
06840 
06841     byte_p = (u_char *) & test;
06842     *byte_p++ = 0x11;
06843     *byte_p = 0x22;
06844     if (test == 0x1122)
06845         return (0);
06846     else
06847         return (1);
06848 }
06849 
06882 int
06883 edt_set_buffer_size(EdtDev * edt_p, uint_t index, uint_t size, uint_t write_flag)
06884 
06885 {
06886 
06887     buf_args sysargs;
06888 
06889     if (edt_p->ring_buffers[index])
06890     {
06891         if (size > (u_int) edt_p->rb_control[index].size)
06892         {
06893             edt_msg_perror(EDTFATAL, "edt_set_buffer_size: Attempt to set size greater than allocated\n");
06894             return -1;
06895         }
06896 
06897         sysargs.index = index;
06898         sysargs.writeflag = write_flag;
06899         sysargs.addr = 0;
06900         sysargs.size = size;
06901 
06902         return edt_ioctl(edt_p, EDTS_BUF, &sysargs);
06903 
06904     }
06905     else
06906     {
06907         edt_msg_perror(EDTFATAL, "edt_set_buffer_size: Attempt to set size on unallocated buffer\n");
06908 
06909         return -1;
06910     }
06911 }
06912 
06913 int
06914 edt_set_max_buffers(EdtDev *edt_p, int newmax)
06915 
06916 {
06917     edt_msg(EDTDEBUG, "edt_set_max_buffers\n");
06918 
06919     return 
06920         edt_ioctl(edt_p, EDTS_MAX_BUFFERS, &newmax);
06921 }
06922 
06923 int
06924 edt_get_max_buffers(EdtDev *edt_p)
06925 
06926 {
06927     u_int val;
06928 
06929     if (edt_p->devid == DMY_ID) val = MAX_DMA_BUFFERS ;
06930     else edt_ioctl(edt_p, EDTG_MAX_BUFFERS, &val);
06931 
06932     return val;
06933 
06934 }
06935 
06936 
06937 void
06938 edt_resume(EdtDev * edt_p)
06939 {
06940     u_int dmy ;
06941 
06942     edt_msg(EDTDEBUG, "edt_resume\n") ;
06943     edt_ioctl(edt_p, EDTS_RESUME, &dmy);
06944 }
06945 
06970 uint_t
06971 edt_get_todo(EdtDev * edt_p)
06972 {
06973     u_int todo ;
06974     if (edt_p->devid == DMY_ID)
06975         todo = dmy_started ;
06976     else
06977         edt_ioctl(edt_p, EDTG_TODO, &todo);
06978     edt_msg(EDTDEBUG, "edt_get_todo: %d\n",todo) ;
06979     return todo;
06980 }
06981 
06982 uint_t
06983 edt_get_drivertype(EdtDev * edt_p)
06984 {
06985     u_int type ;
06986     edt_ioctl(edt_p, EDTG_DRIVER_TYPE, &type);
06987     edt_msg(EDTDEBUG, "edt_get_drivertype: %x\n",type) ;
06988     return type;
06989 }
06990 
06991 /* only for testing */
06992 int
06993 edt_set_drivertype(EdtDev *edt_p, u_int type)
06994 {
06995     edt_msg(EDTDEBUG, "edt_set_drivertype\n");
06996     return edt_ioctl(edt_p, EDTS_DRIVER_TYPE, &type);
06997 }
06998 
07022 int
07023 edt_get_reftime(EdtDev * edt_p, u_int * timep) 
07024 {
07025     /* we return sec and nsec - change to usec */
07026     u_int   timevals[2];
07027 
07028     edt_ioctl(edt_p, EDTG_REFTIME, &timevals[0]);
07029     edt_msg(EDTDEBUG, "%x %x ",
07030         timevals[0],
07031         timevals[1]) ;
07032     timep[0] = timevals[0];
07033     timep[1] = timevals[1];
07034     return (timevals[1]) ;
07035 }
07036 
07037 void
07038 edt_set_timetype(EdtDev * edt_p, u_int type)
07039 {
07040     edt_ioctl(edt_p, EDTS_TIMETYPE, &type);
07041 }
07042 
07043 void
07044 edt_set_abortintr(EdtDev * edt_p, u_int val)
07045 {
07046     edt_ioctl(edt_p, EDTS_ABORTINTR, &val);
07047 }
07048 
07049 
07050 caddr_t
07051 edt_mapmem(EdtDev *edt_p, u_int addr, int size)
07052 {
07053     caddr_t     ret;
07054 #if defined(VXWORKS) || defined(_NT_) || defined(__APPLE__)
07055     edt_buf tmp;
07056 
07057     tmp.value = size;
07058     tmp.desc = addr;
07059 
07060     edt_ioctl(edt_p, EDTS_MAPMEM, &tmp);
07061     /* KLUDGE */
07062     ret = (caddr_t) tmp.desc ;
07063     edt_msg(EDTDEBUG, "edt_mapmem(%x, %x) %x %x\n", addr, size, tmp.desc,tmp.value);
07064     return (ret);
07065 #else
07066     ret = (caddr_t) mmap((caddr_t)0, size, PROT_READ|PROT_WRITE,
07067         MAP_SHARED, edt_p->fd, addr);
07068     if (ret == ((caddr_t)-1)) {
07069         perror("mmap call");
07070         return(0) ;
07071     }
07072     return(ret) ;
07073 #endif
07074 }
07075 
07076 u_int edt_get_mappable_size(EdtDev *edt_p)
07077 
07078 {
07079     u_int value = 0;
07080 
07081     edt_ioctl(edt_p, EDTG_MEMSIZE, &value);
07082 
07083     return value;
07084 
07085 }
07086 
07087 
07088 #ifdef __sun
07089 
07095 static id_t
07096 schedinfo(char *name, short *maxpri)
07097 {
07098     pcinfo_t info;
07099     tsinfo_t *tsinfop;
07100     rtinfo_t *rtinfop;
07101 
07102     (void) strcpy(info.pc_clname, name);
07103     if (priocntl(0L, 0L, PC_GETCID, (char *) &info) == -1L)
07104     {
07105         return (-1);
07106     }
07107     if (strcmp(name, "TS") == 0)
07108     {
07109         tsinfop = (struct tsinfo *) info.pc_clinfo;
07110         *maxpri = tsinfop->ts_maxupri;
07111     }
07112     else if (strcmp(name, "RT") == 0)
07113     {
07114         rtinfop = (struct rtinfo *) info.pc_clinfo;
07115         *maxpri = rtinfop->rt_maxpri;
07116     }
07117     else
07118     {
07119         return (-1);
07120     }
07121     return (info.pc_cid);
07122 }
07123 
07128 void
07129 edt_set_RT(u_int pri)
07130 {
07131     pcparms_t pcparms;
07132     rtparms_t *rtparmsp;
07133     id_t    rtID;
07134     short   maxrtpri;
07135 
07136     /* Get highest valid RT priority. */
07137     if ((rtID = schedinfo("RT", &maxrtpri)) == -1)
07138     {
07139         edt_msg_perror(EDTFATAL, "schedinfo failed for RT");
07140         exit(2);
07141     }
07142 
07143     /* Change proc to RT, highest prio - 1, default time slice */
07144     pcparms.pc_cid = rtID;
07145     rtparmsp = (struct rtparms *) pcparms.pc_clparms;
07146     rtparmsp->rt_pri = maxrtpri - (1 + pri) ;
07147     rtparmsp->rt_tqnsecs = RT_TQDEF;
07148 
07149     if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, (char *) &pcparms) == -1)
07150     {
07151         edt_msg_perror(EDTFATAL, "PC_SETPARMS failed");
07152         exit(3);
07153     }
07154 }
07155 #endif /* __sun */
07156 
07157 /*
07158 * below are utility routines, intended primarily for EDT library
07159 * internal use but available for application use if desired
07160 */
07161 
07165 void
07166 edt_fwd_to_back(char *str)
07167 {
07168     char   *p = str;
07169 
07170     while (*p != '\0')
07171     {
07172         if (*p == '/')
07173             *p = '\\';
07174         ++p;
07175     }
07176 }
07177 
07181 void
07182 edt_back_to_fwd(char *str)
07183 {
07184     char   *p = str;
07185 
07186     while (*p != '\0')
07187     {
07188         if (*p == '\\')
07189             *p = '/';
07190         ++p;
07191     }
07192 }
07193 
07194 
07195 
07200 void
07201 edt_correct_slashes(char *str)
07202 {
07203 #if _NT_
07204     edt_fwd_to_back(str);
07205 #else
07206     edt_back_to_fwd(str);
07207 #endif
07208 }
07209 
07229 int
07230 edt_access(char *fname, int perm)
07231 {
07232     int     ret;
07233 
07234     edt_correct_slashes(fname);
07235 #ifdef _NT_
07236     ret = _access(fname, perm);
07237 #elif defined(VXWORKS)
07238 
07239     ret = 0 ;
07240 #else
07241     ret = access(fname, perm);
07242 #endif
07243     return ret;
07244 }
07245 
07246 #ifdef PCD
07247 /*
07248 * SSE (fast serial) support.
07249 */
07250 
07251 /* These bits are in hi word of long, must split into two to do AND's, OR's */
07252 #define XPLLBYP (0x1<<17)
07253 #define XPLLCLK (0x1<<18)
07254 #define XPLLDAT (0x1<<19)
07255 #define XPLLSTB (0x1<<20)
07256 
07257 #define XC_X16  (0x00)          /* PC Only: hi for SCLK=16MHz, not SCLK=CCLK */
07258 #define XC_AVSEL (0x80)         /* GP Only: hi for SCLK=AVCLK, not SCLK=16MHz*/
07259 
07260 #define XC_CCLK (0x01)          /* These codes interpreted by sse_wpp() */
07261 #define XC_DIN  (0x02)          /*  Xilinx config data and clock */
07262 #define XC_PROG (0x04)          /*  inverted in sse_wpp() when driving PROGL */
07263 #define XC_INITL (0x04)         /* Actual bit positions in status register */
07264 #define XC_DONE  (0x08)
07265 
07266 /* Write encoded data to parallel port data register */
07267 static void
07268 sse_wpp(EdtDev *edt_p, int val)
07269 {
07270     unsigned char bits;
07271 
07272     bits = edt_intfc_read(edt_p, PCD_FUNCT) & 0x08;     /* Preserve SWAPEND */
07273 
07274     if (val & XC_DIN)   bits |= 0x04;
07275     if (val & XC_PROG)  bits |= 0x01;
07276     if (val & XC_AVSEL) bits |= 0x80;
07277 
07278     edt_intfc_write(edt_p, PCD_FUNCT, bits);
07279 
07280     if (val & XC_CCLK)          /* strobe the clock hi then low */
07281     {
07282         edt_intfc_write(edt_p, PCD_FUNCT, (unsigned char) (bits | 0x02));
07283         edt_intfc_write(edt_p, PCD_FUNCT, bits);
07284     }
07285 
07286     edt_msg(EDTDEBUG, "sse_wpp(%02x)  ", bits);
07287 }
07288 
07289 
07290 static int
07291 sse_spal(EdtDev * edt_p, int v)
07292 {
07293     edt_msleep(1);
07294     edt_intfc_write(edt_p, PCD_PAL0, (unsigned char) (v >> 0));
07295     edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (v >> 8));
07296     edt_intfc_write(edt_p, PCD_PAL2, (unsigned char) (v >> 16));
07297 
07298     return (edt_intfc_read(edt_p, PCD_PAL3));
07299 }
07300 
07301 static void
07302 sse_xosc(EdtDev * edt_p, int val)
07303 {
07304     int     n, s;       /* First set up MC12430 lines, CLK=0, DAT=0, STB=0 */
07305     int   gspv = edt_intfc_read(edt_p, PCD_PAL0)
07306         | edt_intfc_read(edt_p, PCD_PAL1) << 8 
07307         | edt_intfc_read(edt_p, PCD_PAL2) << 16;
07308 
07309     gspv = (gspv & ~XPLLBYP & ~XPLLCLK & ~XPLLDAT & ~XPLLSTB);
07310     sse_wpp(edt_p, 0);
07311 
07312     edt_msleep(1);              /* Shut down AVSEL */
07313 
07314     for (n = 13; n >= 0; n--)
07315     {                           /* Send 14 bits of data to MC12430 */
07316         s = val & (0x1 << n);   /* get the current data bit */
07317 
07318         if (s)
07319         {
07320             sse_spal(edt_p, gspv | XPLLDAT);    /* Set up data, then clock it */
07321             sse_spal(edt_p, gspv | XPLLDAT | XPLLCLK);
07322         }
07323         else
07324         {
07325             sse_spal(edt_p, gspv);      /* Strobe clock only, no data */
07326             sse_spal(edt_p, gspv | XPLLCLK);
07327         }
07328 
07329         edt_msg(EDTDEBUG, "sse_xosc:  n:%d  s:%x\n", n, (s != 0));
07330     }
07331 
07332     sse_spal(edt_p, gspv | XPLLSTB);    /* Strobe serial_load */
07333     sse_spal(edt_p, gspv);              /* Clear the strobe */
07334 
07335 
07336     if ((val >> 11) == 6)
07337     {
07338         gspv |= XPLLBYP;
07339         sse_spal(edt_p, gspv);
07340 
07341         sse_wpp(edt_p, XC_AVSEL);       /* On GP, drive SCLK from AV9110 */
07342     }
07343     else
07344         sse_wpp(edt_p, 0);
07345 
07346 
07347     if (XC_X16)
07348         sse_wpp(edt_p, XC_X16);         /* On PC, drive SCLK with 16 MHz ref */
07349 }
07350 
07351 
07352 double
07353 sse_set_out_clk(EdtDev * edt_p, double fmhz)
07354 {                               /* Set ECL clock to freq specified in MHz */
07355     int     m, n, t, hex, nn, fx;
07356     edt_pll avp;
07357     double  avf = 0.0; /* should this have a more reasonable value? --doug */
07358 
07359     if (fmhz < 0)
07360     {
07361         printf("sse_set_pll_freq: Invalid argument %f\n", fmhz);
07362         return 0;
07363     }
07364 
07365     fx = (int) fmhz;
07366 
07367     if ((fmhz > 800.0) || (fmhz < 0.000050))
07368     {
07369         printf("Error, %f MHz requested.  Min of 0.000050, max of 800Mhz\n",
07370             fmhz);
07371         return (0);
07372     }
07373     else if (fx > 400)
07374     {
07375         t = 0;
07376         n = 3;
07377         m = fx / 2;
07378         nn = 1;
07379     }                           /* Every 2 MHz */
07380     else if (fx > 200)
07381     {
07382         t = 0;
07383         n = 0;
07384         m = fx;
07385         nn = 2;
07386     }                           /* Every 1 MHz */
07387     else if (fx > 100)
07388     {
07389         t = 0;
07390         n = 1;
07391         m = fx * 2;
07392         nn = 4;
07393     }                           /* Every 500 KHz */
07394     else if (fx >= 50)
07395     {
07396         t = 0;
07397         n = 2;
07398         m = fx * 4;
07399         nn = 8;
07400     }                           /* Every 250 KHz */
07401     else
07402     {
07403         avf = edt_find_vco_frequency(edt_p, fmhz * 1E6, (double) 30E6, &avp, 0);
07404         if (avf != 0)
07405             edt_set_out_clk(edt_p, &avp);       /* Load AV9110 */
07406         t = 6;
07407         n = 3;
07408         m = 200;
07409         nn = 4;                 /* Put MC12430 in bypass, use AV9110 */
07410     }
07411 
07412     hex = (t << 11) | (n << 9) | m;
07413 
07414     sse_xosc(edt_p, hex);       /* Load MC12430 hw */
07415 
07416     if (t != 6)
07417     {
07418         edt_msg(EDTDEBUG,
07419             "sse_set_out_clk:  %f MHz  MC12430: t:%d  n:%d  m:%d  hex:0x%04x\n",
07420             (2.0 * m / nn), t, n, m, hex);
07421         return (2.0 * m / nn);  /* Freq of MC12430 in MHz */
07422     }
07423     else
07424     {
07425         edt_msg(EDTDEBUG,
07426             "sse_set_out_clk: %f MHz AV9110:  m:%d n:%d v:%d r:%d h:%d l:%d x:%d\n",
07427             (avf / 1E6), avp.m, avp.n, avp.v, avp.r, avp.h, avp.l, avp.x);
07428         return (avf / 1E6);     /* Freq of AV9110 in MHz */
07429     }
07430 }
07431 
07432 
07433 
07434 
07435 void
07436 sse_shift(EdtDev *edt_p, int shift)
07437 {
07438     int n ;
07439     unsigned char  old;
07440 
07441     if (shift)
07442     {
07443         old = edt_intfc_read(edt_p, PCD_PAL1) & ~0x02;
07444         edt_intfc_write(edt_p, PCD_PAL1, old);
07445 
07446         for (n = 0; n < shift; n++)
07447         {
07448             edt_msleep(1);
07449             edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (0x02 | old));
07450             edt_msleep(1);
07451             edt_intfc_write(edt_p, PCD_PAL1, old);
07452         }
07453     }
07454 }
07455 /*
07456 To swallow a clock on channel 0, strobe bit 9,  so PCD_PAL1 0x02
07457 To swallow a clock on channel 1, strobe bit 21, so PCD_PAL2 0x20
07458 */
07459 void
07460 sse_shift_chan(EdtDev *edt_p, int shift, int channel)
07461 {
07462     int n ;
07463     unsigned char  old;
07464 
07465     if (shift) {
07466         if (channel==0) {
07467             old = edt_intfc_read(edt_p, PCD_PAL1) & ~0x02;
07468             edt_intfc_write(edt_p, PCD_PAL1, old);
07469 
07470             for (n = 0; n < shift; n++)
07471             {
07472                 edt_msleep(1);
07473                 edt_intfc_write(edt_p, PCD_PAL1, (unsigned char) (0x02 | old));
07474                 edt_msleep(1);
07475                 edt_intfc_write(edt_p, PCD_PAL1, old);
07476             }
07477         } else {
07478             old = edt_intfc_read(edt_p, PCD_PAL2) & ~0x20;
07479             edt_intfc_write(edt_p, PCD_PAL2, old);
07480 
07481             for (n = 0; n < shift; n++)
07482             {
07483                 edt_msleep(1);
07484                 edt_intfc_write(edt_p, PCD_PAL2, (unsigned char) (0x20 | old));
07485                 edt_msleep(1);
07486                 edt_intfc_write(edt_p, PCD_PAL2, old);
07487             }
07488         }
07489     }
07490 }
07491 #endif /* PCD */
07492 
07493 
07494 #ifdef P11W
07495 
07496 #include "p11w.h"
07497 
07498 u_short
07499 p11w_get_command(EdtDev * edt_p)
07500 {
07501     return (edt_reg_read(edt_p, P11_COMMAND));
07502 }
07503 
07504 void
07505 p11w_set_command(EdtDev * edt_p, u_short val)
07506 {
07507     edt_reg_write(edt_p, P11_COMMAND, val);
07508 }
07509 
07510 u_short
07511 p11w_get_config(EdtDev * edt_p)
07512 {
07513     return (edt_reg_read(edt_p, P11_CONFIG));
07514 }
07515 
07516 void
07517 p11w_set_config(EdtDev * edt_p, u_short val)
07518 {
07519     edt_reg_write(edt_p, P11_CONFIG, val);
07520 }
07521 
07522 u_short
07523 p11w_get_data(EdtDev * edt_p)
07524 {
07525     return (edt_reg_read(edt_p, P11_DATA));
07526 }
07527 
07528 void
07529 p11w_set_data(EdtDev * edt_p, u_short val)
07530 {
07531     edt_reg_write(edt_p, P11_DATA, val);
07532 }
07533 
07534 u_short
07535 p11w_get_stat(EdtDev * edt_p)
07536 {
07537     return (edt_reg_read(edt_p, P11_STATUS));
07538 }
07539 
07540 u_int
07541 p11w_get_count(EdtDev * edt_p)
07542 {
07543     return (edt_reg_read(edt_p, P11_COUNT));
07544 }
07545 
07546 /*
07547 * The following routine is deprecated.  Use the one following
07548 * this, p11w_set_abortdma_onintr().     Mark  6/04
07549 */
07550 void
07551 p11w_abortdma_onattn(EdtDev *edt_p, int flag)
07552 {
07553     int arg = 0x11 ;
07554     u_short readcmd ;
07555 
07556 
07557     if (flag)
07558     {
07559         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07560         readcmd |= P11W_EN_ATT ;
07561         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07562 
07563         edt_ioctl(edt_p, EDTS_CUSTOMER, &arg) ;
07564     }
07565     else
07566     {
07567         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07568         readcmd &= ~P11W_EN_ATT ;
07569         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07570 
07571         arg = 0 ;
07572         edt_ioctl(edt_p, EDTS_CUSTOMER, &arg) ;
07573     }
07574 }
07575 
07576 void
07577 p11w_set_abortdma_onintr(EdtDev *edt_p, int flag)
07578 {
07579     u_short readcmd, writecmd ;
07580 
07581     if (flag == 0)
07582     {
07583         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07584         readcmd &= ~P11W_EN_ATT ;
07585         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07586 
07587         edt_ioctl(edt_p, P11G_WRITE_COMMAND, &writecmd) ;
07588         writecmd &= ~P11W_EN_ATT ;
07589         edt_ioctl(edt_p, P11S_WRITE_COMMAND, &writecmd) ;
07590     }
07591 
07592     edt_ioctl(edt_p, EDTS_ABORTDMA_ONINTR, &flag) ;
07593 
07594     if (flag)
07595     {
07596         edt_ioctl(edt_p, P11G_READ_COMMAND, &readcmd) ;
07597         readcmd |= P11W_EN_ATT ;
07598         edt_ioctl(edt_p, P11S_READ_COMMAND, &readcmd) ;
07599 
07600         edt_ioctl(edt_p, P11G_WRITE_COMMAND, &writecmd) ;
07601         writecmd |= P11W_EN_ATT ;
07602         edt_ioctl(edt_p, P11S_WRITE_COMMAND, &writecmd) ;
07603     }
07604 }
07605 
07606 #endif                          /* P11W */
07607 
07618 int
07619 edt_device_id(EdtDev *edt_p)
07620 {
07621     if (edt_p)
07622         return edt_p->devid;
07623     return -1;
07624 }
07625 
07630 char *
07631 edt_idstr(int id)
07632 {
07633     switch(id)
07634     {
07635     case P11W_ID:               return("pci 11w");
07636     case P16D_ID:               return("pci 16d");
07637     case PDV_ID:                return("pci dv");
07638     case PDVA_ID:               return("pci dva");
07639     case PDVA16_ID:             return("pci dva16");
07640     case PDVK_ID:               return("pci dvk");
07641     case PDVRGB_ID:             return("pci dv-rgb");
07642     case PDV44_ID:              return("pci dv44");
07643     case PDVCL_ID:              return("pci dv c-link");
07644     case PDVCL2_ID:             return("pci dv cls");
07645     case PE4DVCL_ID:            return("pcie4 dv c-link");
07646     case PE8DVCL_ID:            return("pcie8 dv c-link");
07647     case PDVAERO_ID:            return("pcd dv aero serial");
07648     case PCD20_ID:              return("pci cd-20");
07649     case PCD40_ID:              return("pci cd-40");
07650     case PCD60_ID:              return("pci cd-60");
07651     case PCDA_ID:               return("pci cda");
07652     case PCDCL_ID:              return("pci cd cl");
07653     case PGP20_ID:              return("pci gp-20");
07654     case PGP40_ID:              return("pci gp-40");
07655     case PGP60_ID:              return("pci gp-60");
07656 
07657     case PGP_THARAS_ID:         return("pci gp-tharas");
07658     case PGP_ECL_ID:            return("pci gp-ecl");
07659     case PCD_16_ID:             return("pci cd-16");
07660     case PCDA16_ID:             return("pci cda16");
07661 
07662     case PDVFCI_AIAG_ID:        return("pci-fci aiag");
07663     case PDVFCI_USPS_ID:        return("pci-fci usps");
07664     case PCDFCI_SIM_ID:         return("pci-fci sim");
07665     case PCDFCI_PCD_ID:         return("pci-fci pcd");
07666     case PCDFOX_ID:             return("pcd fox");
07667     case PDVFOX_ID:             return("pci dv fox");
07668     case PE4DVFOX_ID:           return("pcie4 dv fox");
07669     case PE8DVFOX_ID:           return("pcie8 dv fox");
07670     case P53B_ID:               return("pci 53b");
07671     case PDVFOI_ID:             return("pdv foi");
07672     case PSS4_ID:               return("pci ss-4");
07673     case PSS16_ID:              return("pci ss-16");
07674     case PGS4_ID:               return("pci gs-4");
07675     case PGS16_ID:              return("pci gs-16");
07676     case PE8LX1_ID:             return("pcie8 lx-1");
07677     case PE8LX4_ID:             return("pcie8 lx-4");
07678     case PE8LX16_ID:            return("pcie8 lx-16");
07679     case DMY_ID:                return("dummy");
07680     case DMYK_ID:               return("dummy pci dvk/44/foi");
07681     default:                    return("unknown");
07682     }
07683 }
07684 
07685 
07692 #if defined(VXWORKS) || defined(TEST_VXWORKS)
07693 /* writable command string for vxworks calling edt_system() */
07694 char edt_vxw_cmdstr[512];
07695 
07696 /*
07697 * The following two arrays are used to register a function name with a
07698 * function pointer for vxworks calling edt_system().  Only 32 unique
07699 * program names are supported; most programs use less than 5.
07700 *
07701 * STRATEGY:  Preference is simplicity, but works with most applications.
07702 */
07703 static char *program_func_name[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07704 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07705 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07706 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
07707 static void * edt_vx_system_func[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07708 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07709 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07710 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
07711 
07712 /*
07713 * VxWorks programs calling edt_system() must first register the progam name
07714 * and the program function.
07715 */
07716 int
07717 edt_vx_system_register_func(const char *funcstr, int (funcptr)(char *))
07718 {
07719     int i;
07720 
07721     for (i = 0; i < 32; i++)
07722     {
07723         if (program_func_name[i] == NULL)
07724             break;
07725     }
07726 
07727     if (i == 32)
07728         return(-1);
07729     else
07730     {
07731         program_func_name[i] =  edt_alloc(strlen(funcstr) + 1);
07732         strcpy(program_func_name[i], funcstr);
07733         edt_vx_system_func[i] = funcptr;
07734         return 0;
07735     }
07736 }
07737 #endif
07738 
07739 int
07740 edt_system(const char *cmdstr)
07741 {
07742 #if defined(_NT_)
07743 
07744     int ret;
07745     char *newstr = malloc(512) ;
07746     char *p = newstr ;
07747     int nowait = 0;
07748     char *arg[32] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07749         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07750         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07751         NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
07752     };
07753     int i ;
07754 
07755     if (cmdstr == NULL || *cmdstr == '\0')
07756         return(0) ;
07757 
07758     strncpy(newstr, cmdstr, 511) ;
07759     for (i = 0; (i < 32) && (p && *p); i++)
07760     {
07761         while (*p == ' ' || *p == '\t')
07762             *p++ = '\0' ;
07763 
07764         arg[i] = p ;
07765 
07766         while (*p != ' ' && *p != '\t' && *p != '\0')
07767             ++ p ;
07768     }
07769 
07770     if (*arg[i-1] == '&')
07771     {
07772         arg[i-1] = NULL;
07773         nowait = 1;
07774     }
07775 
07776     ret = spawnv((nowait) ? _P_NOWAIT : _P_WAIT, arg[0], arg);
07777     free(newstr);
07778     return ret;
07779 #elif defined(VXWORKS) || defined(TEST_VXWORKS)
07780     /*
07781     * VxWorks programs calling edt_system() must first register the progam name
07782     * and the program function.  Here the string argument to edt_system() is
07783     * parsed into the command name and options.  The command name is looked up
07784     * and matched with a function pointer, then the function is called with
07785     * the option string.
07786     */
07787     {
07788         int i;
07789         char *cmd;
07790         char *opts;
07791         char *tmp;
07792         int (*fnp)(char *);
07793 
07794         strncpy(edt_vxw_cmdstr, cmdstr, 511);
07795         cmd = edt_vxw_cmdstr;
07796         opts = strchr(edt_vxw_cmdstr, ' ');
07797 
07798         if (opts)
07799             *opts++ = '\0';
07800 
07801         tmp = strrchr(edt_vxw_cmdstr, '/');
07802         if (tmp)
07803             cmd = tmp + 1;
07804 
07805 
07806         edt_msg(EDTDEBUG, "VXWORKS_test: edt_system(%s, %s)\n", cmd, opts);
07807 #if defined(TEST_VXWORKS)
07808         printf("VXWORKS_test: edt_system(%s, %s)\n", cmd, opts);
07809 #endif
07810 
07811         for (i = 0; i < 32; i++)
07812         {
07813             if (program_func_name[i] == NULL)
07814                 return -1;
07815             else if (strncmp(program_func_name[i], cmd, 511) == 0)
07816             {
07817                 fnp = (int (*)(char*)) edt_vx_system_func[i];
07818                 edt_msg(EDTDEBUG, "VXWORKS_test: found name %s func %p\n", cmd, fnp);
07819                 return fnp(opts);
07820             }
07821         }
07822 
07823         if (i == 32) /* Not found */
07824         {
07825             edt_msg(EDTDEBUG, "VXWORKS_test: name not found %s, must be registered with edt_vx_system_register_func()\n", cmd);
07826             return -1;
07827         }
07828     }
07829 #else
07830 
07831     int ret ;
07832 
07833     ret = system(cmdstr) ;
07834 
07835 #if defined(__sun) || defined(__linux__) || defined(__APPLE__)
07836     if (ret == -1 || WIFEXITED(ret) == 0)
07837         return -1 ;
07838     else
07839         return WEXITSTATUS(ret) ;
07840 #else
07841     return ret ;
07842 #endif
07843 #endif
07844 }
07845 
07846 #define MEZZ_PATH_FIELD_CHAR '|'
07847 
07848 char *
07849 edt_get_last_bitpath(EdtDev *edt_p)
07850 
07851 {
07852     FILE *f;
07853     static char cache_name[MAXPATH];
07854 
07855     sprintf(cache_name, ".interface_bitfile.%d", edt_p->unit_no);
07856 
07857     if (f = fopen(cache_name, "r"))
07858     {
07859 
07860         fgets(cache_name, MAXPATH, f);
07861 
07862         if (cache_name[strlen(cache_name)-1] == '\n')
07863             cache_name[strlen(cache_name)-1] = 0;
07864 
07865         fclose(f);
07866 
07867         return cache_name;
07868     }
07869 
07870     return NULL;
07871 }
07872 
07873 
07874 void
07875 edt_set_last_bitpath(EdtDev *edt_p, const char *fullpath)
07876 
07877 {
07878     FILE *f;
07879     char cache_name[MAXPATH];
07880 
07881     sprintf(cache_name, ".interface_bitfile.%d", edt_p->unit_no);
07882 
07883     if (f = fopen(cache_name, "w"))
07884     {
07885 
07886         fputs(fullpath, f);
07887 
07888         fclose(f);
07889 
07890     }
07891 }
07892 
07893 
07907 int
07908 edt_set_mezz_chan_bitpath(EdtDev *edt_p, const char *bitpath, int channel)
07909 {
07910     edt_bitpath pathbuf, chan0, chan1;
07911     const char *s1;
07912     int sp;
07913     int rc;
07914     EdtDev *chan0_edt_p;
07915 
07916     if (edt_p->channel_no)
07917     {
07918         chan0_edt_p = edt_open(EDT_INTERFACE, edt_p->unit_no);
07919     }
07920     else
07921     {
07922         chan0_edt_p = edt_p;
07923     }
07924 
07925     /* scan back for / in path - we may not have room for full path */
07926 
07927     sp = (int) strlen(bitpath) - 1;
07928 
07929     while (sp >= 0 && bitpath[sp] != '/' && bitpath[sp] != '\\')
07930         sp --;
07931 
07932     if (sp >= 0)
07933         sp++;
07934     else
07935         sp = 0;
07936 
07937     s1 = bitpath + sp;
07938 
07939     edt_get_mezz_chan_bitpath(chan0_edt_p,chan0, sizeof(chan0),0);
07940     edt_get_mezz_chan_bitpath(chan0_edt_p,chan1, sizeof(chan1),1);
07941 
07942     if (channel == 0)
07943         sprintf(pathbuf,"%s%c%s",s1,MEZZ_PATH_FIELD_CHAR,chan1);
07944     else
07945         sprintf(pathbuf,"%s%c%s",chan0, MEZZ_PATH_FIELD_CHAR, s1);
07946 
07947     rc = edt_ioctl(chan0_edt_p, EDTS_MEZZ_BITPATH, pathbuf);
07948 
07949     /* make sure chan0_edt_p->bfd is up to date */     
07950     edt_get_mezz_chan_bitpath(chan0_edt_p, chan0_edt_p->bfd.mezz_name0,
07951         sizeof(chan0_edt_p->bfd.mezz_name0),0);
07952     edt_get_mezz_chan_bitpath(chan0_edt_p, chan0_edt_p->bfd.mezz_name1,
07953         sizeof(chan0_edt_p->bfd.mezz_name1),1);
07954 
07955     if (chan0_edt_p != edt_p)
07956         edt_close(chan0_edt_p);
07957 
07958     return rc;
07959 }
07960 
07961 
07976 int
07977 edt_get_mezz_chan_bitpath(EdtDev *edt_p, char *bitpath, int size, int channel)
07978 {
07979     int ret = 0 ;
07980     edt_bitpath pathbuf ;
07981     char *s2, *s3;
07982     int sp;
07983     /* split into channels */
07984     EdtDev *chan0_edt_p;
07985 
07986     if (edt_p->channel_no)
07987     {
07988         chan0_edt_p = edt_open(EDT_INTERFACE, edt_p->unit_no);
07989     }
07990     else
07991     {
07992         chan0_edt_p = edt_p;
07993     }
07994 
07995     ret = edt_ioctl(chan0_edt_p, EDTG_MEZZ_BITPATH, pathbuf);
07996 
07997     if (chan0_edt_p != edt_p)
07998         edt_close(chan0_edt_p);
07999 
08000     s2 = pathbuf;
08001     sp = 0;
08002     while (sp < (int)strlen(pathbuf) && pathbuf[sp] != MEZZ_PATH_FIELD_CHAR)
08003         sp++;
08004 
08005     s3 = s2 + sp;
08006     if (s3[0] == MEZZ_PATH_FIELD_CHAR)