Stefan Schuermans commited on 2012-03-21 21:43:38
              Showing 6 changed files, with 101 additions and 32 deletions.
            
| ... | ... | @@ -116,25 +116,25 @@ static void arp_send_request(unsigned char ip[4]) | 
| 116 | 116 | // ARP request for own IP address | 
| 117 | 117 | if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request | 
| 118 | 118 |        ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address | 
| 119 | - struct arp_packet arp_reply; | |
| 119 | + struct arp_packet_pad arp_reply; | |
| 120 | 120 |  | 
| 121 | 121 | // build ARP reply | 
| 122 | - arp_reply.arp_hdr.hw_type = htons(0x0001); // ethernet | |
| 123 | - arp_reply.arp_hdr.proto_type = htons(0x0800); // IP | |
| 124 | - arp_reply.arp_hdr.hw_len = 0x06; // length of a MAC address | |
| 125 | - arp_reply.arp_hdr.proto_len = 0x04; // length of an IP address | |
| 126 | - arp_reply.arp_hdr.op = htons(0x0002); // ARP reply | |
| 127 | - mac_cpy(arp_reply.arp_hdr.src_mac, config_mac.mac); // own MAC | |
| 128 | - ip_cpy(arp_reply.arp_hdr.src_ip, config_ip.ip); // own IP | |
| 129 | - mac_cpy(arp_reply.arp_hdr.dest_mac, | |
| 122 | + arp_reply.p.arp_hdr.hw_type = htons(0x0001); // ethernet | |
| 123 | + arp_reply.p.arp_hdr.proto_type = htons(0x0800); // IP | |
| 124 | + arp_reply.p.arp_hdr.hw_len = 0x06; // length of a MAC address | |
| 125 | + arp_reply.p.arp_hdr.proto_len = 0x04; // length of an IP address | |
| 126 | + arp_reply.p.arp_hdr.op = htons(0x0002); // ARP reply | |
| 127 | + mac_cpy(arp_reply.p.arp_hdr.src_mac, config_mac.mac); // own MAC | |
| 128 | + ip_cpy(arp_reply.p.arp_hdr.src_ip, config_ip.ip); // own IP | |
| 129 | + mac_cpy(arp_reply.p.arp_hdr.dest_mac, | |
| 130 | 130 | arp_pack->arp_hdr.src_mac); // requestor's MAC | 
| 131 | - ip_cpy(arp_reply.arp_hdr.dest_ip, | |
| 131 | + ip_cpy(arp_reply.p.arp_hdr.dest_ip, | |
| 132 | 132 | arp_pack->arp_hdr.src_ip); // requestor's IP | 
| 133 | 133 |  | 
| 134 | 134 | // send ARP reply | 
| 135 | - mac_cpy(arp_reply.eth_hdr.dest, | |
| 136 | - arp_reply.arp_hdr.dest_mac); // ethernet destination address | |
| 137 | - arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP | |
| 135 | + mac_cpy(arp_reply.p.eth_hdr.dest, | |
| 136 | + arp_reply.p.arp_hdr.dest_mac); // ethernet destination address | |
| 137 | + arp_reply.p.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP | |
| 138 | 138 | ethernet_send(&arp_reply, sizeof(arp_reply)); | 
| 139 | 139 |  | 
| 140 | 140 | return; | 
| ... | ... | @@ -3,7 +3,7 @@ | 
| 3 | 3 |  | 
| 4 | 4 | #include "ethernet.h" | 
| 5 | 5 |  | 
| 6 | -/// header of an ARP packet | |
| 6 | +/// header of ARP packet | |
| 7 | 7 | struct arp_header | 
| 8 | 8 |  { | 
| 9 | 9 | unsigned short hw_type; | 
| ... | ... | @@ -17,13 +17,16 @@ struct arp_header | 
| 17 | 17 | unsigned char dest_ip[4]; | 
| 18 | 18 | } __attribute__((packed)); | 
| 19 | 19 |  | 
| 20 | -/// an ARP packet | |
| 20 | +/// ARP packet | |
| 21 | 21 | struct arp_packet | 
| 22 | 22 |  { | 
| 23 | 23 | struct ethernet_header eth_hdr; | 
| 24 | 24 | struct arp_header arp_hdr; | 
| 25 | 25 | } __attribute__((packed)); | 
| 26 | 26 |  | 
| 27 | +/// ARP packet with padding | |
| 28 | +ETHERNET_PAD(arp_packet); | |
| 29 | + | |
| 27 | 30 | /// initialize | 
| 28 | 31 | extern void arp_init(void); | 
| 29 | 32 |  | 
| ... | ... | @@ -5,9 +5,13 @@ static volatile unsigned int *const eth_ptr = | 
| 5 | 5 | (volatile unsigned int *)0x80000400; | 
| 6 | 6 |  | 
| 7 | 7 | static unsigned int eth_idx_hw; | 
| 8 | -static unsigned int eth_rx_buf[2][381]; // max frame len: 1522 byte = 380.5 int | |
| 8 | +static unsigned int eth_rx_buf[2][381]; /* max frame: 1522 byte = 380.5 int */ | |
| 9 | 9 | static unsigned int *eth_rx_pos; | 
| 10 | 10 |  | 
| 11 | +static unsigned int eth_rx_cnt; | |
| 12 | + | |
| 13 | +static unsigned int eth_tx_cnt; | |
| 14 | + | |
| 11 | 15 | /** | 
| 12 | 16 | * @brief set MAC address | 
| 13 | 17 | * @param[in] mac MAC address | 
| ... | ... | @@ -52,12 +56,21 @@ void eth_mac_init(void) | 
| 52 | 56 | /** initialize receiver */ | 
| 53 | 57 | void eth_rx_init(void) | 
| 54 | 58 |  { | 
| 55 | - // give buffer 0 to HW | |
| 59 | + /* give buffer 0 to HW */ | |
| 56 | 60 | eth_idx_hw = 0; | 
| 57 | 61 | eth_rx_new_buf(eth_rx_buf[0], sizeof(eth_rx_buf[0])); | 
| 58 | - // buffer 1 owned by SW is empty | |
| 62 | + /* buffer 1 owned by SW is empty */ | |
| 59 | 63 | eth_rx_buf[1][0] = 0; | 
| 60 | 64 | eth_rx_pos = eth_rx_buf[1]; | 
| 65 | + /* no packets received yet */ | |
| 66 | + eth_rx_cnt = 0; | |
| 67 | +} | |
| 68 | + | |
| 69 | +/** initialize transmitter */ | |
| 70 | +void eth_tx_init(void) | |
| 71 | +{ | |
| 72 | + /* no packets transmitted yet */ | |
| 73 | + eth_tx_cnt = 0; | |
| 61 | 74 | } | 
| 62 | 75 |  | 
| 63 | 76 | /** | 
| ... | ... | @@ -68,42 +81,59 @@ void eth_rx_init(void) | 
| 68 | 81 | */ | 
| 69 | 82 | int eth_rx(void **pptr, unsigned int *psz) | 
| 70 | 83 |  { | 
| 71 | - // current SW buffer is empty and HW buffer contains a packet | |
| 84 | + /* current SW buffer is empty and HW buffer contains a packet */ | |
| 72 | 85 |    if (*eth_rx_pos == 0 && eth_rx_get_pos() != eth_rx_buf[eth_idx_hw]) { | 
| 73 | - // swap buffers | |
| 86 | + /* swap buffers */ | |
| 74 | 87 | eth_idx_hw = 1 - eth_idx_hw; | 
| 75 | - // give new HW buffer to HW | |
| 88 | + /* give new HW buffer to HW */ | |
| 76 | 89 | eth_rx_new_buf(eth_rx_buf[eth_idx_hw], sizeof(eth_rx_buf[eth_idx_hw])); | 
| 77 | - // start reading packet data at begin of new SW buffer | |
| 90 | + /* start reading packet data at begin of new SW buffer */ | |
| 78 | 91 | eth_rx_pos = eth_rx_buf[1 - eth_idx_hw]; | 
| 79 | 92 | } | 
| 80 | 93 |  | 
| 81 | - // SW buffer contains a packet | |
| 94 | + /* SW buffer contains a packet */ | |
| 82 | 95 |    if (*eth_rx_pos > 0) { | 
| 83 | - // return size and pointer, advance position | |
| 96 | + /* return size and pointer, advance position */ | |
| 84 | 97 | *psz = *eth_rx_pos; | 
| 85 | 98 | eth_rx_pos++; | 
| 86 | 99 | *pptr = eth_rx_pos; | 
| 87 | 100 | eth_rx_pos += *psz >> 2; | 
| 101 | + ++eth_rx_cnt; /* count received packets */ | |
| 88 | 102 | return 1; | 
| 89 | 103 | } | 
| 90 | 104 |  | 
| 91 | - // no packet received | |
| 105 | + /* no packet received */ | |
| 92 | 106 | return 0; | 
| 93 | 107 | } | 
| 94 | 108 |  | 
| 95 | 109 | /** | 
| 96 | 110 | * @brief transmit packet | 
| 97 | - * @param[out] ptr pointer to packet data | |
| 98 | - * @param[out] sz size of packet | |
| 111 | + * @param[in] ptr pointer to packet data | |
| 112 | + * @param[in] sz size of packet | |
| 113 | + * | |
| 114 | + * Padding will be appended if sz is not a multiple of 4 or smaller 60 bytes. | |
| 115 | + * The buffer pointed to by ptr must be sufficiently large. | |
| 99 | 116 | */ | 
| 100 | 117 | void eth_tx(const void *ptr, unsigned int sz) | 
| 101 | 118 |  { | 
| 102 | - while(sz & 3) /* pad with zeros up to next 4 byte boundary */ | |
| 119 | + while(sz < 60 || sz & 3) /* pad with zeros */ | |
| 103 | 120 | ((unsigned char *)ptr)[sz++] = 0; | 
| 104 | 121 | eth_ptr[8] = (unsigned int)ptr; /* start */ | 
| 105 | 122 | eth_ptr[9] = (unsigned int)ptr + sz; /* end */ | 
| 106 | 123 | eth_ptr[10] = 1; /* set flag */ | 
| 107 | 124 | while (eth_ptr[10] == 1); /* wait until processed */ | 
| 125 | + ++eth_tx_cnt; /* count transmitted packets */ | |
| 126 | +} | |
| 127 | + | |
| 128 | +/** get number of received packets */ | |
| 129 | +unsigned int eth_rx_get_cnt(void) | |
| 130 | +{ | |
| 131 | + return eth_rx_cnt; | |
| 132 | +} | |
| 133 | + | |
| 134 | +/** get number of transmitted packets */ | |
| 135 | +unsigned int eth_tx_get_cnt(void) | |
| 136 | +{ | |
| 137 | + return eth_tx_cnt; | |
| 108 | 138 | } | 
| 109 | 139 |  | 
| ... | ... | @@ -7,6 +7,9 @@ void eth_mac_init(void); | 
| 7 | 7 | /** initialize receiver */ | 
| 8 | 8 | void eth_rx_init(void); | 
| 9 | 9 |  | 
| 10 | +/** initialize transmitter */ | |
| 11 | +void eth_tx_init(void); | |
| 12 | + | |
| 10 | 13 | /** | 
| 11 | 14 | * @brief get next received packet | 
| 12 | 15 | * @param[out] *pptr pointer to packet data | 
| ... | ... | @@ -17,10 +20,19 @@ int eth_rx(void **pptr, unsigned int *psz); | 
| 17 | 20 |  | 
| 18 | 21 | /** | 
| 19 | 22 | * @brief transmit packet | 
| 20 | - * @param[out] ptr pointer to packet data | |
| 21 | - * @param[out] sz size of packet | |
| 23 | + * @param[in] ptr pointer to packet data | |
| 24 | + * @param[in] sz size of packet | |
| 25 | + * | |
| 26 | + * Padding will be appended if sz is not a multiple of 4 or smaller 60 bytes. | |
| 27 | + * The buffer pointed to by ptr must be sufficiently large. | |
| 22 | 28 | */ | 
| 23 | 29 | void eth_tx(const void *ptr, unsigned int sz); | 
| 24 | 30 |  | 
| 31 | +/** get number of received packets */ | |
| 32 | +unsigned int eth_rx_get_cnt(void); | |
| 33 | + | |
| 34 | +/** get number of transmitted packets */ | |
| 35 | +unsigned int eth_tx_get_cnt(void); | |
| 36 | + | |
| 25 | 37 | #endif /* #ifndef ETH_H */ | 
| 26 | 38 |  | 
| ... | ... | @@ -1,7 +1,20 @@ | 
| 1 | 1 | #ifndef ETHERNET_H | 
| 2 | 2 | #define ETHERNET_H | 
| 3 | 3 |  | 
| 4 | -/// header of an ethernet packet | |
| 4 | +/** padding at end of packet | |
| 5 | + to reach next size divisible by 4 and at least 60 bytes */ | |
| 6 | +#define ETHERNET_PADDING_SIZE(packet) \ | |
| 7 | + (sizeof(struct packet) >= 60 ? 0 : 60 - sizeof(struct packet)) | |
| 8 | +#define ETHERNET_PADDING(packet) \ | |
| 9 | + unsigned char padding[ETHERNET_PADDING_SIZE(packet)] | |
| 10 | +#define ETHERNET_PAD(packet) \ | |
| 11 | + struct packet ## _pad \ | |
| 12 | +        { \ | |
| 13 | + struct packet p; \ | |
| 14 | + ETHERNET_PADDING(packet); \ | |
| 15 | + } __attribute__((packed)) | |
| 16 | + | |
| 17 | +/// header of ethernet packet | |
| 5 | 18 | struct ethernet_header | 
| 6 | 19 |  { | 
| 7 | 20 | unsigned char dest[6]; | 
| ... | ... | @@ -15,6 +28,9 @@ struct ethernet_packet | 
| 15 | 28 | struct ethernet_header eth_hdr; | 
| 16 | 29 | } __attribute__((packed)); | 
| 17 | 30 |  | 
| 31 | +/// ethernet packet with padding | |
| 32 | +ETHERNET_PAD(ethernet_packet); | |
| 33 | + | |
| 18 | 34 | /** | 
| 19 | 35 | * @brief process a received ethernet packet | 
| 20 | 36 | * @param[in] ptr pointer to data of packet | 
| ... | ... | @@ -55,6 +55,13 @@ void eth_task(void) | 
| 55 | 55 | uart_tx(ptr[i]); | 
| 56 | 56 | ethernet_recv(vptr, sz); | 
| 57 | 57 | } | 
| 58 | + | |
| 59 | + i = eth_rx_get_cnt(); | |
| 60 | + lcd_chr(0, 11, '0' + (i >> 3 & 0x7)); | |
| 61 | + lcd_chr(0, 12, '0' + (i & 0x7)); | |
| 62 | + i = eth_tx_get_cnt(); | |
| 63 | + lcd_chr(0, 14, '0' + (i >> 3 & 0x7)); | |
| 64 | + lcd_chr(0, 15, '0' + (i & 0x7)); | |
| 58 | 65 | } | 
| 59 | 66 |  | 
| 60 | 67 | void tasks(void) | 
| ... | ... | @@ -84,11 +91,12 @@ int main() | 
| 84 | 91 |  | 
| 85 | 92 | eth_mac_init(); | 
| 86 | 93 | eth_rx_init(); | 
| 94 | + eth_tx_init(); | |
| 87 | 95 |  | 
| 88 | 96 | leds_set_state(0x02); | 
| 89 | 97 |  | 
| 90 | 98 | lcd_init(); | 
| 91 | - lcd_str(0, "MIPS I system"); | |
| 99 | + lcd_str(0, "MIPS I"); | |
| 92 | 100 | lcd_str(1, ""); | 
| 93 | 101 |  | 
| 94 | 102 | leds_set_state(0x04); | 
| 95 | 103 |