]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - tools/etermip.c
Local copy of Plasma MIPS project.
[fpga/plasma.git] / tools / etermip.c
1 /*--------------------------------------------------------------------
2  * TITLE: etermip
3  * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4  * DATE CREATED: 6/13/07
5  * FILENAME: etermip.c
6  * PROJECT: Plasma CPU core
7  * COPYRIGHT: Software placed into the public domain by the author.
8  *    Software 'as is' without warranty.  Author liable for nothing.
9  * DESCRIPTION:
10  *    A terminal program supporting downloading new Plasma applications
11  *    and Ethernet packet transfers.  Based on WinPcap example code.
12  *    Requires WinPcap library at http://www.winpcap.org/.
13  *--------------------------------------------------------------------*/
14 #include <windows.h>
15 #include <stdio.h>
16 #include <conio.h>
17
18 //#define SIMULATE_PLASMA
19 //#define USE_WPCAP
20 #ifdef SIMULATE_PLASMA
21 #define USE_WPCAP
22 #endif
23
24 #ifdef USE_WPCAP
25 #if 0
26    #include "pcap.h"
27 #else
28    //From "pcap.h"
29    #define PCAP_ERRBUF_SIZE 256
30    typedef struct pcap_if {
31       struct pcap_if *next;
32       char *name;               /* name to hand to "pcap_open_live()" */
33       char *description;        /* textual description of interface, or NULL */
34       struct pcap_addr *addresses;
35       unsigned long flags;      /* PCAP_IF_ interface flags */
36    } pcap_if_t;
37    struct pcap_pkthdr {
38       struct timeval ts;        /* time stamp */
39       unsigned long caplen;     /* length of portion present */
40       unsigned long len;        /* length this packet (off wire) */
41    };
42    typedef struct pcap pcap_t;
43
44    int pcap_findalldevs(pcap_if_t **, char *);
45    void pcap_freealldevs(pcap_if_t *);
46    pcap_t *pcap_open_live(const char *, int, int, int, char *);
47    int pcap_setnonblock(pcap_t *, int, char *);
48    int pcap_sendpacket(pcap_t *, const u_char *, int);
49    const unsigned char *pcap_next(pcap_t *, struct pcap_pkthdr *);
50 #endif
51
52 //ETHER FIELD                 OFFSET   LENGTH   VALUE
53 #define ETHERNET_DEST         0        //6
54 #define ETHERNET_SOURCE       6        //6
55 #define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806
56 #define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11
57 #define IP_SOURCE             26       //4
58
59 static const unsigned char ethernetAddressNull[] =    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
60 static const unsigned char ethernetAddressPhantom[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
61 static const unsigned char ethernetAddressPhantom2[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
62
63 static pcap_t *adhandle;
64 #endif //USE_WPCAP
65
66 static HANDLE serial_handle;
67 static int PacketBytes, PacketLength, PacketChecksum, Checksum;
68 static int ChecksumOk, ChecksumError;
69 static unsigned char PacketData[2000];
70 static int EthernetActive;
71
72 #ifdef SIMULATE_PLASMA
73    extern void *IPFrameGet(int freeCount);
74    extern int IPProcessEthernetPacket(void *frameIn, int length);
75    extern void IPTick(void);
76    extern void IPInit(void (*frameSendFunction)(), unsigned char macAddress[6], char name[6]);
77    extern void HtmlInit(int UseFiles);
78    extern void ConsoleInit(void);
79    static void *ethFrame;
80 #endif
81
82
83 #ifdef USE_WPCAP
84 int WinPcapInit(void)
85 {
86         pcap_if_t *alldevs;
87         pcap_if_t *d;
88         int inum;
89         int i=0;
90    int choice = -1;
91         char errbuf[PCAP_ERRBUF_SIZE];
92
93    /* Retrieve the device list */
94         if(pcap_findalldevs(&alldevs, errbuf) == -1)
95         {
96                 printf("Error in pcap_findalldevs: %s\n", errbuf);
97                 exit(1);
98         }
99         
100         /* Print the list */
101         for(d = alldevs; d; d=d->next)
102         {
103                 printf("%d. %s", ++i, d->name);
104                 if (d->description)
105                         printf(" (%s)\n", d->description);
106                 else
107                         printf(" (No description available)\n");
108       if(strstr(d->description, "eneric") == 0 && strstr(d->description, "Linux") == 0)
109       {
110          if(choice == -1)
111             choice = i;
112          else
113             choice = -2;
114       }
115         }
116         
117         if(i==0)
118         {
119                 printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
120                 return -1;
121         }
122         
123    if(choice >= 0)
124       inum = choice;
125    else if(i == 1)
126       inum = 1;
127    else
128    {
129            printf("Enter the interface number (1-%d):",i);
130            scanf("%d", &inum);
131    }
132    printf("inum = %d\n", inum);
133         
134         if(inum < 1 || inum > i)
135         {
136                 printf("\nInterface number out of range.\n");
137                 /* Free the device list */
138                 pcap_freealldevs(alldevs);
139                 return -1;
140         }
141         
142         /* Jump to the selected adapter */
143         for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
144         
145         /* Open the adapter */
146         if ((adhandle = pcap_open_live(d->name, // name of the device
147                                        65536,   // 65536 grants that the whole packet will be captured on all the MACs.
148                                        1,       // promiscuous mode (nonzero means promiscuous)
149                                        10,      // read timeout
150                                        errbuf   // error buffer
151                                        )) == NULL)
152         {
153                 printf("\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
154                 /* Free the device list */
155                 pcap_freealldevs(alldevs);
156                 return -1;
157         }
158         
159         printf("\nlistening on %s...\n", d->description);
160         
161         /* At this point, we don't need any more the device list. Free it */
162         pcap_freealldevs(alldevs);
163  
164    /* start the capture */
165    pcap_setnonblock(adhandle, 1, errbuf);
166
167    return 0;
168 }
169
170
171 void EthernetSendPacket(const unsigned char *packet, int length)
172 {
173    if(EthernetActive == 0)
174       WinPcapInit();
175    EthernetActive = 1;\r
176    //if((rand() % 8) == 0) return;\r
177    pcap_sendpacket(adhandle, packet, length);
178 }
179
180
181 /* Callback function invoked by libpcap for every incoming packet */
182 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
183 {
184 #ifndef SIMULATE_PLASMA
185    int i, checksum;
186    unsigned char buf[80];
187    DWORD count;
188 #else
189    int rc;
190 #endif
191    (void)param;
192
193    if(EthernetActive == 0)
194       return;
195    if(pkt_data[ETHERNET_FRAME_TYPE] != 0x08)
196       return;  //not IP or ARP
197    if(pkt_data[ETHERNET_FRAME_TYPE+1] != 0x00 &&
198       pkt_data[ETHERNET_FRAME_TYPE+1] != 0x06)
199       return;  //not IP or ARP
200    if(memcmp(pkt_data, ethernetAddressNull, 6) &&      //not broadcast address
201       memcmp(pkt_data+ETHERNET_DEST, ethernetAddressPhantom, 6) &&
202       memcmp(pkt_data+ETHERNET_DEST, ethernetAddressPhantom2, 6))
203       return;
204
205 #ifndef SIMULATE_PLASMA
206    //Send the ethernet packet over the serial port
207    buf[0] = 0xff;
208    buf[1] = (unsigned char)(header->len >> 8);
209    buf[2] = (unsigned char)header->len;
210    checksum = 0;
211    for(i = 0; i < (int)header->len; ++i)
212       checksum += pkt_data[i];
213    buf[3] = (unsigned char)checksum;
214    WriteFile(serial_handle, buf, 4, &count, NULL);
215    WriteFile(serial_handle, pkt_data, header->len, &count, NULL);
216 #else
217    if(ethFrame == NULL)
218       ethFrame = IPFrameGet(0);
219    if(ethFrame == NULL)
220       return;
221    memcpy(ethFrame, pkt_data, header->len);
222    rc = IPProcessEthernetPacket(ethFrame, header->len);
223    if(rc)
224       ethFrame = NULL;
225 #endif
226 }
227
228
229 static void UartPacketRead(int value)
230 {
231    if(PacketBytes == 0 && value == 0xff)
232    {
233       ++PacketBytes;
234    }
235    else if(PacketBytes == 1)
236    {
237       ++PacketBytes;
238       PacketLength = value << 8;
239    }
240    else if(PacketBytes == 2)
241    {
242       ++PacketBytes;
243       PacketLength |= value;
244       if(PacketLength > 1000)
245       {
246          PacketBytes = 0;
247          printf("Eterm Length Bad! (%d)\n", PacketLength);
248       }
249    }
250    else if(PacketBytes == 3)
251    {
252       ++PacketBytes;
253       PacketChecksum = value;
254       Checksum = 0;
255    }
256    else if(PacketBytes >= 4)
257    {
258       if(PacketBytes - 4 < sizeof(PacketData))
259          PacketData[PacketBytes - 4] = (unsigned char)value;
260       Checksum += value;
261       ++PacketBytes;
262       if(PacketBytes - 4 >= PacketLength)
263       {
264          if((unsigned char)Checksum == PacketChecksum)
265          {
266             ++ChecksumOk;
267             EthernetSendPacket(PacketData, PacketLength);
268          }
269          else
270          {
271             ++ChecksumError;
272             //printf("ChecksumError(%d %d)!\n", ChecksumOk, ChecksumError);
273          }
274          PacketBytes = 0;
275       }
276    }
277 }
278 #endif //USE_WPCAP
279
280 /**************************************************************/
281
282 long SerialOpen(char *name, long baud)
283 {
284    DCB dcb;
285    COMMTIMEOUTS comm_timeouts;
286    BOOL rc;
287    serial_handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE,
288       0, NULL, OPEN_EXISTING, 0, NULL);
289    if(serial_handle == INVALID_HANDLE_VALUE) 
290       printf("Serial Port In Use!\n");
291    rc = SetupComm(serial_handle, 16000, 16000);
292    if(rc == FALSE) 
293       printf("Serial port already in use!!!\n");
294    rc = GetCommState(serial_handle, &dcb);
295    if(rc == FALSE) 
296       printf("ERROR2\n");
297    dcb.BaudRate = baud;
298    dcb.fBinary = 1;
299    dcb.fParity = 0;
300    dcb.ByteSize = 8;
301    dcb.StopBits = 0; //ONESTOPBIT;
302    dcb.fOutX = 0;
303    dcb.fInX = 0;
304    dcb.fNull = 0;
305    dcb.Parity = 0;
306    dcb.fOutxCtsFlow = 0;
307    dcb.fOutxDsrFlow = 0;
308    dcb.fOutX = 0;
309    dcb.fInX = 0;
310    dcb.fRtsControl = 0;
311    dcb.fDsrSensitivity = 0;
312    rc = SetCommState(serial_handle, &dcb);
313    if(rc == FALSE) 
314       printf("ERROR3\n");
315    rc = GetCommTimeouts(serial_handle, &comm_timeouts);
316    if(rc == FALSE) 
317       printf("ERROR4\n");
318    comm_timeouts.ReadIntervalTimeout = MAXDWORD;  //non-blocking read
319    comm_timeouts.ReadTotalTimeoutMultiplier = 0;
320    comm_timeouts.ReadTotalTimeoutConstant = 0;
321    comm_timeouts.WriteTotalTimeoutMultiplier = 0;  //blocking write
322    comm_timeouts.WriteTotalTimeoutConstant = 0;
323    rc = SetCommTimeouts(serial_handle, &comm_timeouts);
324    if(rc == FALSE) 
325       printf("ERROR5\n");
326    return(0);
327 }
328
329
330 long SerialRead(unsigned char *data, unsigned long length)
331 {
332    DWORD count, bytes;
333    unsigned char buf[8];
334
335    count = 0;
336    for(;;)
337    {
338       ReadFile(serial_handle, buf, 1, &bytes, NULL);
339       if(bytes == 0)
340          break;
341 #ifdef USE_WPCAP
342       if(buf[0] == 0xff || PacketBytes)
343          UartPacketRead(buf[0]);
344       else
345 #endif
346          data[count++] = buf[0];
347       if(count >= length)
348          break;
349    }
350    return count;
351 }
352
353 //****************************************************
354
355 #define BUF_SIZE 1024*1024
356 void SendFile(void)
357 {
358    FILE *in;
359    unsigned char *buf;
360    long length;
361    DWORD count;
362
363    in=fopen("test.bin", "rb");
364    if(in==NULL) {
365       printf("Can't find test.bin\n");
366       return;
367    }
368    buf = (unsigned char*)malloc(BUF_SIZE);
369    memset(buf, 0, BUF_SIZE);
370    length = (int)fread(buf, 1, BUF_SIZE, in);
371    fclose(in);
372    printf("Sending test.bin (length=%d bytes) to target...\n", length);
373    WriteFile(serial_handle, buf, length, &count, NULL);
374    printf("Done downloading\n");
375    free(buf);
376 }
377
378
379 int main(int argc, char *argv[])
380 {
381    unsigned int ticksLast = GetTickCount();
382    int length;
383    unsigned char buf[80];
384    DWORD count;
385    unsigned int ticks;
386    int downloadSkip = 0;
387    (void)argc;
388    (void)argv;
389
390    //WinPcapInit();
391 #ifndef SIMULATE_PLASMA
392    SerialOpen("COM1", 57600);
393    if(argc != 2 || strcmp(argv[1], "none"))
394       SendFile();
395    else
396       downloadSkip = 1;
397 #else
398    IPInit(EthernetSendPacket, NULL, NULL);
399    HtmlInit(1);
400    ConsoleInit();
401 #endif
402
403    for(;;)
404    {
405       // Read keypresses
406       while(kbhit())
407       {
408          buf[0] = (unsigned char)getch();
409          if(downloadSkip && buf[0] == '`')
410             SendFile();
411          WriteFile(serial_handle, buf, 1, &count, NULL);
412       }
413
414       // Read UART
415       for(;;)
416       {
417          length = SerialRead(buf, sizeof(buf));
418          if(length == 0)
419             break;
420          buf[length] = 0;
421          printf("%s", buf);
422       }
423
424 #ifdef USE_WPCAP
425       // Read Ethernet
426       while(EthernetActive)
427       {
428          struct pcap_pkthdr header;
429          const u_char *pkt_data;
430          pkt_data = pcap_next(adhandle, &header);
431          if(pkt_data == NULL)
432             break;
433          if(EthernetActive)
434             packet_handler(NULL, &header, pkt_data);
435       }
436 #endif
437       Sleep(10);
438       ticks = GetTickCount();
439       if(ticks - ticksLast > 1000)
440       {
441 #ifdef SIMULATE_PLASMA
442          IPTick();
443 #endif
444          ticksLast = ticks;
445       }
446    }
447 }
448