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