-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatmelwebserver - v0-94-1.c
1747 lines (1644 loc) · 49.6 KB
/
atmelwebserver - v0-94-1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*Project: AVR Web Server
by: Eric Mesa and Richard West
based upon version 0.93 beta
by: Jeremy
Current working version 0.95
Version 0.94.1 9 Apr 2005
1) Eliminated minor redundancies (eg x++ instead of x=x+1)
Version 0.94 9 Apr 2005
1) Fixed browser compatibility problems by correctly padding the html header
This involved adding 12 spaces at the front and a \r\n at the end
Version 0.93.1 6 April 2005
1) Fixed typoes in copying from PDF
Version 0.93 4 March 2004
1) Added Checksum for incoming TCP packets (fixed)
2) Added TCP data sending function (only sends 1 packet at a time Window functionality should be done)
3)Increased packet size from 96 - 300 (since we can have 576 max packet length)
4)Added HTTP functions and HTTP sample
5)Added DHCP functionality
6)Need to tweak the TCP_close() functionality
7) Note: The webbrowesers use the RST fucntion whenever it is closed. Don't think will need the TCP_close()
*****TESTING*****
6) DHCP WORKING!
7) IMCP working!!
7) HTTP up!!
8) TCP resend lost data working (tested)
8) (fixed) didn't do the setting of packets properly only set the 1st byte must do all bytes
*/
//*******************************************
//* PORT MAP
//*******************************************
//PORT C = rtldata - data bus RCTL8019 and AVR
// 0 SD0
// 1 SD1
// 2 SD2
// 3 SD3
// 4 SD4
// 5 SD5
// 6 SD6
// 7 SD7
// PORT B
// 0 SA0
// 1 SA1
// 2 SA2
// 3 SA3
// 4 SA4
// 5
// 6
// 7 make this the rst_pin
// PORT A
// temperature sensor port
//PORT D
//0 RXD
//1 TXD
//2 INT0 --> for EEPROM only
// 3 EESK
//4 EEDI
//5 EEDO
//6 ior_pin
//7 iow_pin
#include<mega32.h>
#include<string.h>
#include<stdio.h>
#include<delay.h>
#include<stdlib.h>
#define ISO_G 0x47
#define ISO_E 0x45
#define ISO_T 0x54
#define ISO_slash 0x2f
#define ISO_c 0x63
#define ISO_g 0x67
#define ISO_i 0x69
#define ISO_space 0x20
#define ISO_nl 0x0a
#define ISO_cr 0x0d
#define ISO_a 0x61
#define ISO_t 0x74
#define ISO_hash 0x23
#define ISO_period 0x2e
//define the connection structure for a single TCP socket (multiple connections)
char flash *req_page[100];
unsigned int page_size;
//added extra \r\n after Content-type for compatibility with everyone other than IE
flash char flash *index[71] = {" HTTP/1.1 200 OK\r\n","Server: My MEng Project\r\n","Content-type: text/html\r\n",
"\r\n<html>\r\n",
"<head>\r\n","<title>ECE MEng Project Cornell University 2003~4 Done by Jeremy</title>\r\n",
"<meta http-equiv=","","Content-Type","","content=","","text/html; charset=iso-8859-1","",">\r\n",
"</head>\r\n","<body bgcolor=","","#FFFFFF","",">\r\n",
"<h1><strong><font colour=","","#0000FF", ""," face=","","Arial, Helvetica, sans-serif","",">WELCOME TO ATMEL WEBSERVER</font></strong></h1>\r\n"
"<p> </p>\r\n",
"<p><strong><font colour=","","#000FF","","face=","","Arial, Helvetica, sans-serif","",">This webserver is running entirely on a mega32 and using an EDTP packet wacker</font></strong></p>\r\n",
"<p><strong><font colour=","","#000FF","","face=","","Arial, Helvetica, sans-serif","",">This project was done by Tzeming Tan, Jeremy supervised by Dr. Bruce R. Land.</font></strong></p>\r\n",
"<p>Cornell University</p>",
"<p>ATMEL embedded webserver</p>"
"<p>TCP/IP is the communcatiosn protocol most widely used for accessing the internet\r\n",
"today. The objective of this project is to introduce this protocol to the ATMEL\r\n",
"Mega 32 Microcontroller chip such that it can run as a simple webserver which\r\n",
"can then be adapted for useful lab-based applications.</p>\r\n",
"<p>Although the Mega 32 and the development board will only be able to run limited\r\n",
"web functions, it is a relatively inexpensive device compared to high power\r\n",
"web servers. Therefore it can still have many applications for example, connecting\r\n",
"the microcontroller to a thermometer which will display the current temperature on a browser.<br>\r\n",
"The current temperature is now:", "<font color=#FF0000>","%","</font>"," degrees F",
"<p> </p>\r\n",
"<p>link to ECE 476 website <a href=","","http://instruct1.cit.cornell.edu/courses/ee476/","",">here</a>.<br>",
"<p> </p>\r\n",
"<p><br>\r\n</p>\r\n<p> </p>\r\n</body>\r\n</html>"};
unsigned int size_index = 71;
unsigned int http_state = 0;
unsigned int sendflag = 0;
unsigned int pageendflag = 0;
char temperature = 0;
char temp[5];
float voltage; //scaled input voltage
unsigned int Ain;
//*****************************
//* FUNCTION PROTOTYPES
//*****************************
void http_server(void);
void tcp(void);
void tcp_close(void);
void assemble_ack(void);
void write_rtl(unsigned char regaddr, unsigned char regdata);
void read_rtl(unsigned char regaddr);
void get_packet(void);
void setipaddrs(void);
void cksum(void);
void echo_packet(void);
//x is the index number, y is the character number
void pack_html(unsigned int page, unsigned int x, unsigned int y);
//void pack_html(flash char flash*page[], unsigned int x, unsigned int y);
#define INDEX 0
unsigned int dex,pos = 0;
unsigned int rollback,counter = 0;
//end of pack html function
void send_tcp_packet(void);
void arp(void);
void icmp(void);
void udp(void);
void udp_send(void);
//DHCP FUCNTIONS
void dhcp(void);
void dhcp_setip(void);
//Temperature function
void gettemp(void);
//*******************************************
//* IP ADDRESS DEFINITION
//* This is the Ethernet Module IP address
//* You may change this to any valid address
//*******************************************
unsigned char MYIP[4] = {192,168,2,255};
unsigned char client[4];
unsigned char serverid[4];
//*****************************************
//* HARDWARE (MAC) ADDRESS DEFINITION
//* This is the Ethernet Module hardware address
//* You may change this to any valid address
//*****************************************
char MYMAC[6]={'J','e','s','t','e','r'};
//*****************************************
//* Recieve Ring Buffer Header Layout
//* This is the 4-byte header that resides in front of the
//* data packet in the receive buffer
//******************************************
unsigned char pageheader[4];
#define enetpacketstatus 0x00
#define nextblock_ptr 0x01
#define enetpacketLenL 0x02
#define enetpacketLenH 0x03
//*******************************************
//* Ethernet Header Layout
//*******************************************
unsigned char packet[700]; //700 bytes of packet space
#define enetpacketDest0 0x00
//destination mac address
#define enetpacketDest1 0x01
#define enetpacketDest2 0x02
#define enetpacketDest3 0x03
#define enetpacketDest4 0x04
#define enetpacketDest5 0x05
#define enetpacketSrc0 0x06
//source mac address
#define enetpacketSrc1 0x07
#define enetpacketSrc2 0x08
#define enetpacketSrc3 0x09
#define enetpacketSrc4 0x0A
#define enetpacketSrc5 0x0B
#define enetpacketType0 0x0C
//type/length field
#define enetpacketType1 0x0D
#define enetpacketData 0x0E
//IP data area begins here
//******************************************
//* ARP Layout
//******************************************
#define arp_hwtype 0x0E
#define arp_prtype 0x10
#define arp_hwlen 0x12
#define arp_prlen 0x13
#define arp_op 0x14
#define arp_shaddr 0x16
//arp source mac address
#define arp_sipaddr 0x1C
//arp source IP address
#define arp_thaddr 0x20
//arp target mac address
#define arp_tipaddr 0x26
//arp target ip address
//****************************************
//* IP Header Layout
//****************************************
#define ip_vers_len 0x0E
//IP version and header length
#define ip_tos 0x0F
//IP type of service
#define ip_pktlen 0x10
//packet length
#define ip_id 0x12
//datagram ID
#define ip_frag_offset 0x14
//fragment offset
#define ip_ttl 0x16
//time to live
#define ip_proto 0x17
//protocol (ICMP=1, TCP=6, UDP=11)
#define ip_hdr_cksum 0x18
//header checksum
#define ip_srcaddr 0x1A
//IP address of source
#define ip_destaddr 0x1E
//IP aaddress of destination
#define ip_data 0x22
//IP data area
//************************************
//* TCP Header Layout
//************************************
#define TCP_srcport 0x22
//TCP source port
#define TCP_destport 0x24
//TCP destination port
#define TCP_seqnum 0x26
//sequence number
#define TCP_acknum 0x2A
//acknowledgement number
#define TCP_hdrflags 0x2E
//4-bit header len(DATA OFFSET) and flags
#define TCP_window 0x30
//window size
#define TCP_cksum 0x32
//TCP checksum
#define TCP_urgentptr 0x34
//urgent pointer
#define TCP_data 0x36
//option/data
//*********************************************
//* TCP Flags
//* IN flags represent incoming bits
//* OUT flags represent outgoing bits
//* 576 octets(8xbit) max datalength
//*********************************************
#define FIN_IN (packet[TCP_hdrflags+1] & 0x01)
#define SYN_IN (packet[TCP_hdrflags+1] & 0x02)
#define RST_IN (packet[TCP_hdrflags+1] & 0x04)
#define PSH_IN (packet[TCP_hdrflags+1] & 0x08)
#define ACK_IN (packet[TCP_hdrflags+1] & 0x10)
#define URG_IN (packet[TCP_hdrflags+1] & 0x20)
//corrected typeo on FIN_OUT (7 Apr 2005) was missing | before the = (also SYN_OUT,RST_OUT,PSH_OUT,ACK_OUT,URG_OUT
#define FIN_OUT packet[TCP_hdrflags+1] |= 0x01
//00000001
#define NO_FIN packet[TCP_hdrflags+1] &= 0x62
//00111110
#define SYN_OUT packet[TCP_hdrflags+1] |= 0x02
//00000010
#define NO_SYN packet[TCP_hdrflags+1] &= 0x61
//00111101
#define RST_OUT packet[TCP_hdrflags+1] |= 0x04
//00000100
#define PSH_OUT packet[TCP_hdrflags+1] |= 0x08
//00001000
#define ACK_OUT packet[TCP_hdrflags+1] |= 0x10
//00010000
#define NO_ACK packet[TCP_hdrflags+1] &= 0x47
//00101111
#define URG_OUT packet[TCP_hdrflags+1] |= 0x20
//00100000
//*******************************************
//* Port Definitions
//* This address is used by TCP for HTTP server function
//* This can be changed to any valid port number
//* as long as you modify your code to recognize
//* the new port number
//*******************************************
#define MY_PORT_ADDRESS 0x50
//80 decimal for internet
//*******************************************
//* IP Protocol Types
//*******************************************
#define PROT_ICMP 0x01
#define PROT_TCP 0x06
#define PROT_UDP 0x11
//*******************************************
//* ICMP Header
//*******************************************
#define ICMP_type ip_data
#define ICMP_code ICMP_type+1
#define ICMP_cksum ICMP_code+1
#define ICMP_id ICMP_chsum+2
#define ICMP_seqnum ICMP_id+2
#define ICMP_data ICMP_seqnum+2
//******************************************
//* UDP Header and DHCP headers
//******************************************
#define UDP_srcport ip_data
#define UDP_destport UDP_srcport + 2
#define UDP_len UDP_destport + 2
#define UDP_cksum UDP_len + 2
#define UDP_data UDP_cksum + 2
#define DHCP_op UDP_cksum + 2
#define DHCP_htype DHCP_op + 1
#define DHCP_hlen DHCP_htype+1
#define DHCP_hops DHCP_hlen+1
#define DHCP_xid DHCP_hops + 1
#define DHCP_secs DHCP_xid + 4
#define DHCP_flags DHCP_secs + 2
#define DHCP_ciaddr DHCP_flags + 2
#define DHCP_yiaddr DHCP_ciaddr + 4
#define DHCP_siaddr DHCP_yiaddr + 4
#define DHCP_giaddr DHCP_siaddr + 4
#define DHCP_chaddr DHCP_giaddr+4
#define DHCP_sname DHCP_chaddr + 16
#define DHCP_file DHCP_sname + 64
#define DHCP_options DHCP_file + 128
//DHCP states
#define DHCP_DIS 0
#define DHCP_OFF 1
#define DHCP_ACK 2
unsigned int dhcpstate = DHCP_DIS;
//****************************************
//* REALTEK CONTROL REGISTER OFFSETS
//* All offsets in Page 0 unless otherwise specified
//****************************************
#define CR 0x00
#define PSTART 0x01
#define PAR0 0x01
//Page 1
#define CR9346 0x01
//Page 3
#define PSTOP 0x02
#define BNRY 0x03
#define TSR 0x04
#define TPSR 0x04
#define TBCR0 0x05
#define NCR 0x05
#define TBCR1 0x06
#define ISR 0x07
#define CURR 0x07
//Page 1
#define RSAR0 0x08
#define CRDA0 0x08
#define RSAR1 0x09
#define CRDAL 0x09
#define RBCR0 0x0A
#define RBCR1 0x0B
#define RSR 0x0C
#define RCR 0x0C
#define TCR 0x0D
#define CNTR0 0x0D
#define DCR 0x0E
#define CNTR1 0x0E
#define IMR 0x0F
#define CNTR2 0x0F
#define RDMAPORT 0x10
#define RSTPORT 0x18
//************************************************************
//* RTL8019AS INITIAL REGISTER VALUES
//************************************************************
#define rcrval 0x04
#define tcrval 0x00
#define dcrval 0x58
//was 0x48
#define imrval 0x11
//PRX and OVW interrupt enabled
#define txstart 0x40
#define rxstart 0x46
#define rxstop 0x60
//*************************************************************
//* RTL8019AS DATA/ADDRESS PIN DEFINITION
//*************************************************************
#define rtladdr PORTB
#define rtldata PORTC
#define tortl DDRC = 0xFF
#define fromrtl DDRC = 0x00
//*************************************************************
//* RTL8019AS 9346 EEPROM PIN DEFINITIONS
//*************************************************************
#define EESK 0x08
//PORTD3 00001000
#define EEDI 0x10
//PORTD4 00010000
#define EEDO 0x20
//PORTD5 00100000
//*************************************************************
//* RTL8019AS PIN DEFINITIONS
//**************************************************************
#define ior_pin 0x40
//PORTD6 01000000
#define iow_pin 0x80
//PORTD7 10000000
#define rst_pin 0x80
//PORTB7 10000000
#define INT0_pin 0x04
//PORTD2 00000100
//*************************************************************
//* RTL8019AS ISR REGISTER DEFINITIONS
//*************************************************************
#define RST 0x80
//10000000
#define RDC 0x40
//01000000
#define OVW 0x10
//00010000
#define PRX 0x01
//00000001
//*************************************************************
//* AVR RAM Definitions
//*************************************************************
//unsigned char aux_data[400]; //tcp received data area (200 char)
unsigned char req_ip[4];
unsigned int DHCP_wait = 0;
int waitcount = 800;
unsigned char *addr,flags,last_line;
unsigned char byte_read,data_H,data_L;
unsigned char resend;
unsigned int i,t,txlen,rxlen,chksum16,hdrlen,tcplen,tcpdatalen_in,dhcpoptlen;
unsigned int tcpdatalen_out,ISN,portaddr,ip_packet_len;
unsigned long ic_chksum,hdr_chksum,my_seqnum,prev_seqnum,client_seqnum,incoming_ack,expected_ack;
//**********************************************************
//* Flags
//**********************************************************
#define synflag 0x01
//00000001
#define finflag 0x02
//00000010
#define synflag_bit flags & synflag
#define finflag_bit flags & finflag
//either we are sending an ack or sending data
unsigned int ackflag = 0;
// for TCP close operations
unsigned int closeflag = 0;
#define iorwport PORTD
#define eeprom PORTD
#define resetport PORTB
//*******************************************************
//* RTL8019AS PIN MACROS
//*******************************************************
#define set_ior_pin iorwport |= ior_pin
#define clr_ior_pin iorwport &= ~ior_pin
#define set_iow_pin iorwport |= iow_pin
#define clr_iow_pin iorwport &= ~iow_pin
#define set_rst_pin resetport |= rst_pin
#define clr_rst_pin resetport &= ~rst_pin
#define clr_EEDO eeprom &= ~EEDO
#define set_EEDO eeprom |= EEDO
#define clr_synflag flags &= ~synflag
#define set_synflag flags |= synflag
#define clr_finflag flags &= ~finflag
#define set_finflag flags |= finflag
#define set_packet32(d,s) packet[d] = make8(s,3); \
packet[d+1] = make8(s,2); \
packet[d+2] = make8(s,1); \
packet[d+3] = make8(s,0);
//converts decimal into words (8bit0
#define make8(var,offset) (var >> (offset*8)) & 0xFF
//joins two 8bit binary into a 16bit binary and converts it to decimal
#define make16(varhigh,varlow) ((varhigh & 0xFF)*0x100) + (varlow & 0xFF)
//joins 4 8 bit numbers to form a 32bit number
#define make32(var1,var2,var3,var4) ((unsigned long)var1<<24)+((unsigned long)var2<<16)+ ((unsigned long)var3<<8)+((unsigned long)var4)
//*******************************************************
//* timer interrupt
//*******************************************************
interrupt[TIM0_COMP] void t0_cmp(void)
{
waitcount--;
if(waitcount<0)
{
waitcount = 9000;
}
}
//******************************************************
//* Application Code
//* Your application code goes here.
//* This particular code echoes the incomeing Telnet data to the LCD
//******************************************************
void http_server()
{
/* Check for GET */
if(http_state = 0 && ( packet[TCP_data] != ISO_G || packet[TCP_data+1] != ISO_E || packet[TCP_data+2] != ISO_T || packet[TCP_data+3] != ISO_space))
{
//if it not a get get we close the connection
tcp_close();
}
else
{
http_state = 1;
//get the sample
//The sleep statement lowers digital noise
//and starts the A/D conversion
#asm
sleep
#endasm
gettemp();
//send the http
//check which file client wants
//set the dataptr to teh file
if(sendflag == 0 && pageendflag == 0)
{
if(rollback)
{
//start from beginning again
dex=0;
pos=0;
}
sendflag=1;
pack_html(INDEX,dex,pos);
counter += tcpdatalen_out;
if(pageendflag == 1)
set_finflag;
send_tcp_packet();
rollback=0;
}
// the send operation has been completed
else if(pageendflag == 1)
{
pageendflag = 0;
dex = 0;
pos = 0;
counter = 0;
rollback = 0;
http_state = 0;
}
}
}
//********************************************************
//* Get Temperature
//*******************************************************
void gettemp()
{
voltage = (float)Ain;
voltage = (voltage/256)*2.6; //(fraction of full scale)*Aref
voltage = voltage/0.02;
ftoa(voltage,3,temp);
}
interrupt [ADC_INT] void adc_done(void)
{
Ain = ADCH;
}
//*******************************************************
//* Perform ARP Response
//* This routine supplies a requesting computer with the
//* Ethernet module's MAC (hardware) address
//*******************************************************
void arp()
{
//start the NIC
write_rtl(CR,0x22);
//load beginning page for transmit buffer
write_rtl(TPSR,txstart);
//set start address for remote DMA operation
write_rtl(RSAR0,0x00);
write_rtl(RSAR1,0x40);
//clear the interrupts
write_rtl(ISR,0xFF);
//load data byte count for remote DMA
write_rtl(RBCR0,0x3C);
write_rtl(RBCR1,0x00);
//do remote write operation
write_rtl(CR,0x12);
//write destination MAC address
for(i=0;i<6;++i)
write_rtl(RDMAPORT,packet[enetpacketSrc0+i]);
//write source MAC address
for(i=0;i<6;++i)
write_rtl(RDMAPORT,MYMAC[i]);
//write typelen hwtype prtype hwlen prlen op:
addr = &packet[enetpacketType0];
packet[arp_op+1] = 0x02;
for(i=0;i<10;++i)
write_rtl(RDMAPORT,*addr++);
//write ethernet module MAC address
for(i=0;i<6;++i)
write_rtl(RDMAPORT,MYMAC[i]);
//write ethernet module IP address
for(i=0;i<4;++i)
write_rtl(RDMAPORT,MYIP[i]);
//write remote MAC address
for(i=0;i<6;++i)
write_rtl(RDMAPORT,packet[enetpacketSrc0+i]);
//write remote IP address
for(i=0;i<4;++i)
write_rtl(RDMAPORT,packet[arp_sipaddr+i]);
//write some pad characeters to fill out the packet to
//the minimum length
for(i=0;i<0x12;++i)
write_rtl(RDMAPORT,0x00);
//make sure the DMA operation has successfully completed
byte_read=0;
while(!(byte_read & RDC))
read_rtl(ISR);
//load number of bytes to be transmitted
write_rtl(TBCR0,0x3C);
write_rtl(TBCR1,0x00);
//send the contents of the transmit buffer onto the network
write_rtl(CR,0x24);
}
//********************************************************
//* Perform ICMP Function
//* This routine responds to a ping
//********************************************************
void icmp()
{
//set echo reply
packet[ICMP_type] = 0x00;
packet[ICMP_code] = 0x00;
//clear the ICMP checksum
packet[ICMP_cksum] = 0x00;
packet[ICMP_cksum+1] = 0x00;
//setup the IP header
setipaddrs();
//calculate the ICMP checksum
hdr_chksum = 0;
hdrlen = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) - \
((packet[ip_vers_len] & 0x0F) * 4);
addr = &packet[ICMP_type];
cksum();
chksum16 = ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
packet[ICMP_cksum] = make8(chksum16,1);
packet[ICMP_cksum+1] = make8(chksum16,0);
//send the ICMP packet along on its way
echo_packet();
}
//****************************************************
//* UDP Function (To be used with DHCP)
//* UDP_srcport = 0, destination is either 67 or 68 IP is
//* 0000000 and 255.255.255.255.255
//****************************************************
void udp()
{
//use port 68 DHCP
if(packet[UDP_destport] == 0x00 && packet[UDP_destport+1] == 0x44)
{
ic_chksum = make16(packet[UDP_cksum],packet[UDP_cksum+1]);
//calculate the UDP checksum
packet[UDP_cksum] = 0x00;
packet[UDP_cksum+1] = 0x00;
hdr_chksum = 0;
hdrlen = 0x08;
addr = &packet[ip_srcaddr];
cksum();
hdr_chksum = hdr_chksum + packet[ip_proto];
hdrlen = 0x02;
addr = &packet[UDP_len];
cksum();
hdrlen = make16(packet[UDP_len],packet[UDP_len+1]);
addr = &packet[UDP_srcport];
cksum();
chksum16 = ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
//perform checksum
if(chksum16 == ic_chksum)
dhcp();
}
}
void udp_send()
{
ip_packet_len = 20+make16(packet[UDP_len],packet[UDP_len+1]);
packet[ip_pktlen] = make8(ip_packet_len,1);
packet[ip_pktlen+1] = make8(ip_packet_len,0);
packet[ip_proto] = PROT_UDP;
//calculate the IP header checksum
packet[ip_hdr_cksum] = 0x00;
packet[ip_hdr_cksum+1] = 0x00;
hdr_chksum = 0;
chksum16 = 0;
hdrlen = (packet[ip_vers_len] & 0x0F)*4;
addr = &packet[ip_vers_len];
cksum();
chksum16 = ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
packet[ip_hdr_cksum] = make8(chksum16,1);
packet[ip_hdr_cksum+1] = make8(chksum16,0);
//set the source port to 68 (client)
packet[UDP_srcport] = 0x00;
packet[UDP_srcport+1] = 0x44;
//set the destination port to 67 (server)
packet[UDP_destport] = 0x00;
packet[UDP_destport+1] = 0x43;
//calculate the UDP checksum
packet[UDP_cksum] = 0x00;
packet[UDP_cksum+1] = 0x00;
hdr_chksum = 0;
hdrlen = 0x08;
addr = &packet[ip_srcaddr];
cksum();
hdr_chksum = hdr_chksum + packet[ip_proto];
hdrlen = 0x02;
addr = &packet[UDP_len];
cksum();
hdrlen = make16(packet[UDP_len],packet[UDP_len+1]);
addr = &packet[UDP_srcport];
cksum();
chksum16 = ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
//rich and I stopped debugging here (aka, we stopped reading)
packet[UDP_cksum] = make8(chksum16,1);
packet[UDP_cksum+1] = make8(chksum16,0);
txlen = ip_packet_len + 14;
//transmit length
if(txlen < 60)
txlen = 60;
data_L = make8(txlen,0);
data_H = make8(txlen,1);
write_rtl(CR,0x22);
read_rtl(CR);
while(byte_read & 0x04)
read_rtl(CR);
write_rtl(TPSR,txstart);
write_rtl(RSAR0,0x00);
write_rtl(RSAR1,0x40);
write_rtl(ISR,0xFF);
write_rtl(RBCR0, data_L);
write_rtl(RBCR1, data_H);
write_rtl(CR,0x12);
//the actual send operation
for(i=0;i<txlen;++i)
write_rtl(RDMAPORT,packet[enetpacketDest0+i]);
byte_read = 0;
while(!(byte_read & RDC))
read_rtl(ISR);
write_rtl(TBCR0, data_L);
write_rtl(TBCR1, data_H);
write_rtl(CR,0x24);
}
void dhcp_setip()
{
//build the IP header
//destination ip = 255.255.255.255
packet[ip_destaddr] = 0xFF;
packet[ip_destaddr + 1] = 0xFF;
packet[ip_destaddr + 2] = 0xFF;
packet[ip_destaddr + 3] = 0xFF;
//source IP = 0.0.0.0
packet[ip_srcaddr] = 0;
packet[ip_srcaddr + 1] = 0;
packet[ip_srcaddr + 2] = 0;
packet[ip_srcaddr + 3] = 0;
//you don't know the destination MAC
packet[enetpacketDest0] = 255;
packet[enetpacketDest1] = 255;
packet[enetpacketDest2] = 255;
packet[enetpacketDest3] = 255;
packet[enetpacketDest4] = 255;
packet[enetpacketDest5] = 255;
//make ethernet module mac address the source address
packet[enetpacketSrc0] = MYMAC[0];
packet[enetpacketSrc1] = MYMAC[1];
packet[enetpacketSrc2] = MYMAC[2];
packet[enetpacketSrc3] = MYMAC[3];
packet[enetpacketSrc4] = MYMAC[4];
packet[enetpacketSrc5] = MYMAC[5];
//calculate IP packet length done by the respective protocols
packet[enetpacketType0] = 0x08;
packet[enetpacketType1] = 0x00;
//set IP header length to 20 bytes
packet[ip_vers_len] = 0x45;
//1st step in getting an IP address
}
//******************************************************
//* DHCP for obtaining IP from router port 67~68 using UDP
//******************************************************
void dhcp()
{
if(dhcpstate == DHCP_DIS)
{
//listen to broadcast
for(i=0;i<4;i++)
MYIP[i] = 255;
packet[DHCP_op] = 1;
packet[DHCP_htype] = 1;
packet[DHCP_hlen] = 6;
packet[DHCP_hops] = 0;
packet[DHCP_xid] = make8(0x31257A1D,3);
packet[DHCP_xid+1] = make8(0x31257A1D,2);
packet[DHCP_xid+2] = make8(0x31257A1D,1);
packet[DHCP_xid+3] = make8(0x31257A1D,0);
for(i=DHCP_secs;i<DHCP_chaddr;i++)
packet[i]=0;
for(i=0;i<6;i++)
packet[DHCP_chaddr+i] = MYMAC[i];
for(i=0;i<10;i++)
packet[DHCP_chaddr+6+i] = 0;
for(i=0;i<192;i++)
packet[DHCP_sname+i]=0;
//magic cookie
packet[DHCP_options] = 99;
packet[DHCP_options+1] = 130;
packet[DHCP_options+2] = 83;
packet[DHCP_options+3] = 99;
//message type
packet[DHCP_options+4] = 53;
packet[DHCP_options+5] = 1;
//DHCP_DISCOVER
packet[DHCP_options+6] = 1;
//Client Identifier
packet[DHCP_options+7] = 61;
packet[DHCP_options+8] = 7;
packet[DHCP_options+9] = 1;
for(i=0;i<6;i++)
packet[DHCP_options+10+i] = MYMAC[i];
//END OPTIONS
packet[DHCP_options+16] = 255;
//lenght of UDP datagram = 8bytes; length of DHCP data = 236 bytes + options
dhcpoptlen = 17;
packet[UDP_len] = make8(244+dhcpoptlen,1);
packet[UDP_len+1] = make8(244+dhcpoptlen,0);
dhcp_setip();
udp_send();
for(i=0;i<4;i++)
MYIP[i] = 255;
DHCP_wait = 1;
//wait for DHCP offer
dhcpstate = DHCP_OFF;
}
//if we have an offer from the server
if(dhcpstate == DHCP_OFF) // && packet[ip_srcaddr] && packet[ip_srcaddr +1] && packet[ip_srcaddr + 2] && packet[ip_srcaddr+3])
{
//check transaction id adn message type
if((DHCP_wait == 2) || ((make32(packet[DHCP_xid], packet[DHCP_xid+1], packet[DHCP_xid+2],packet[DHCP_xid+3]) == 0x31257A1D) && (packet[DHCP_options+4] == 53) && (packet[DHCP_options+5] == 1) && (packet[DHCP_options+6] ==2)))
{
if(DHCP_wait == 1)
for(i=0;i<4;i++)
{
req_ip[i] = packet[DHCP_yiaddr+i];
serverid[i]= packet[ip_srcaddr+i];
}
//stop resending discover
DHCP_wait = 2;
// listen to broadcast
for(i=0;i<4;i++)
MYIP[i] = 255;
//assemble DHCP_req
packet[DHCP_op] = 1;
packet[DHCP_htype] = 1;
packet[DHCP_hlen] = 6;
packet[DHCP_hops] = 0;
packet[DHCP_xid] = make8(0x31257A1D,3);
packet[DHCP_xid+1] = make8(0x31257A1D,2);
packet[DHCP_xid+2] = make8(0x31257A1D,1);
//fixed typeo, this was +1 and should be +3, fixed 7 Apr 2005
packet[DHCP_xid+3] = make8(0x31257A1D,0);
for(i=DHCP_secs;i<DHCP_yiaddr;i++)
packet[i]=0;
for(i=DHCP_siaddr;i<DHCP_chaddr;i++)
packet[i]=0;
for(i=0;i<6;i++)
packet[DHCP_chaddr+i] = MYMAC[i];
for(i=0;i<10;i++)
packet[DHCP_chaddr+6+i] = 0;
for(i=0;i<192;i++)
packet[DHCP_sname+i]=0;
//magic cookie
packet[DHCP_options] = 99;
packet[DHCP_options+1] = 130;
packet[DHCP_options+2] = 83;
packet[DHCP_options+3] = 99;
//message type
packet[DHCP_options+4] = 53;
packet[DHCP_options+5] = 1;
//DHCP_REQUEST
packet[DHCP_options+6] = 3;
//Client Identifier
packet[DHCP_options+7] = 61;
packet[DHCP_options+8] = 7;
packet[DHCP_options+9] = 1;
for(i=0;i<6;i++)
packet[DHCP_options+10+i] = MYMAC[i];
//Requested IP address
packet[DHCP_options+16]=50;
packet[DHCP_options+17]=4;
for(i=0;i<4;i++)
packet[DHCP_options+18+i] = req_ip[i];
for(i=0;i<4;i++)
packet[DHCP_yiaddr+i]=0;
//server ID
packet[DHCP_options+22] = 54;
packet[DHCP_options+23] = 4;
for(i=0;i<4;i++)
packet[DHCP_options+24+i] = serverid[i];
//END OPTIONS
packet[DHCP_options + 28] = 255;
//length of UDP datagram = 8bytes; length of DHCP data = 235 bytes + options
dhcpoptlen = 29;
packet[UDP_len] = make8(244+dhcpoptlen,1);
packet[UDP_len+1] = make8(244+dhcpoptlen,0);
//make a DHCP request
dhcp_setip();
udp_send();
//wait for DHCP ACK
dhcpstate = DHCP_ACK;
}
}
if((dhcpstate == DHCP_ACK) && (packet[ip_srcaddr] == serverid[0]) && (packet[ip_srcaddr+1] == serverid[1]) && (packet[ip_srcaddr+2] == serverid[2]) && (packet[ip_srcaddr + 3] == serverid[3]))
{
//check if message type is an ack
if((make32(packet[DHCP_xid],packet[DHCP_xid+1],packet[DHCP_xid+2],packet[DHCP_xid+3]) == 0x31257A1D)&&(packet[DHCP_options+4]==53)&&(packet[DHCP_options+5] == 1)&&(packet[DHCP_options+6]==5))
{
DHCP_wait = 0;
//take the IP address
for(i=0;i<4;i++)
MYIP[i] = packet[DHCP_yiaddr+i];
}
}
}
//p43
//*****************************************************
//* TCP Function
//* This function uses TCP protocol to interface with the browsser
//* using well known port 80. The application function is called with
//* ever incoming character.
//******************************************************
void tcp()
{
//assemble the destination port address (my) from from the incoming packet
portaddr = make16(packet[TCP_destport],packet[TCP_destport+1]);
//calculate the length of teh data coming in with the packet
//incoming tcp header length
tcplen = ip_packet_len - ((packet[ip_vers_len] & 0x0F) * 4);
//incoming data length =
tcpdatalen_in = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) - \
((packet[ip_vers_len] & 0x0F) * 4)-(((packet[TCP_hdrflags] & 0xF0) >> 4) * 4);
//convert the entire packet into a checksum
//checksum of entire datagram
ic_chksum = make16(packet[TCP_cksum],packet[TCP_cksum+1]);
packet[TCP_cksum] = 0x00;