1 /*
2  *   Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
3  *   Copyright (c) 2013-2018 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
4  *
5  *   The Tcpreplay Suite of tools is free software: you can redistribute it
6  *   and/or modify it under the terms of the GNU General Public License as
7  *   published by the Free Software Foundation, either version 3 of the
8  *   License, or with the authors permission any later version.
9  *
10  *   The Tcpreplay Suite is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with the Tcpreplay Suite.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "config.h"
20 #include "defines.h"
21 #include "common.h"
22 #include "sleep.h"
23 
24 #include <sys/types.h>
25 #include <sys/time.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <string.h>
29 
30 #ifdef HAVE_SYS_EVENT
31 #include <sys/event.h>
32 #endif
33 
34 /* necessary for ioport_sleep() functions */
35 #ifdef HAVE_SYS_IO_H /* Linux */
36 #include <sys/io.h>
37 #elif defined HAVE_ARCHITECTURE_I386_PIO_H /* OS X */
38 #include <architecture/i386/pio.h>
39 #endif
40 
41 #if defined HAVE_IOPORT_SLEEP__
42 static int ioport_sleep_value;
43 #endif
44 
45 void
ioport_sleep_init(void)46 ioport_sleep_init(void)
47 {
48 #if defined HAVE_IOPORT_SLEEP__
49     ioperm(0x80, 1, 1);
50     ioport_sleep_value = inb(0x80);
51 #else
52     err(-1, "Platform does not support IO Port for timing");
53 #endif
54 }
55 
56 void
ioport_sleep(sendpacket_t * sp _U_,const struct timespec * nap _U_,struct timeval * now _U_,bool flush _U_)57 ioport_sleep(sendpacket_t *sp _U_, const struct timespec *nap _U_,
58         struct timeval *now _U_,  bool flush _U_)
59 {
60 #if defined HAVE_IOPORT_SLEEP__
61     struct timeval nap_for;
62     u_int32_t usec;
63     time_t i;
64 
65     TIMESPEC_TO_TIMEVAL(&nap_for, nap);
66 
67     /*
68      * process the seconds, we do this in a loop so we don't have to
69      * use slower 64bit integers or worry about integer overflows.
70      */
71     for (i = 0; i < nap_for.tv_sec; i ++) {
72         usec = SEC_TO_MICROSEC(nap_for.tv_sec);
73         while (usec > 0) {
74             usec --;
75             outb(ioport_sleep_value, 0x80);
76         }
77     }
78 
79     /* process the usec */
80     usec = nap->tv_nsec / 1000;
81     usec --; /* fudge factor for all the above */
82     while (usec > 0) {
83         usec --;
84     	outb(ioport_sleep_value, 0x80);
85     }
86 #else
87     err(-1, "Platform does not support IO Port for timing");
88 #endif
89 
90 #ifdef HAVE_NETMAP
91     if (flush)
92         ioctl(sp->handle.fd, NIOCTXSYNC, NULL);   /* flush TX buffer */
93 #endif /* HAVE_NETMAP */
94 
95     gettimeofday(now, NULL);
96 }
97