static int e1000_uiptxpoll(struct uip_driver_s *dev) { struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; int tail = e1000->tx_ring.tail; /* If the polling resulted in data that should be sent out on the network, * the field d_len is set to a value > 0. */ if (e1000->uip_dev.d_len > 0) { uip_arp_out(&e1000->uip_dev); e1000_transmit(e1000); /* Check if there is room in the device to hold another packet. If not, * return a non-zero value to terminate the poll. */ if (!e1000->tx_ring.desc[tail].desc_status) return -1; } /* If zero is returned, the polling will continue until all connections have * been examined. */ return 0; }
/*stone's solution for lab6-A*/ static int sys_transmit(uint8_t *data, uint32_t len){ if ((uintptr_t) data >= UTOP) return -E_INVAL; else return e1000_transmit(data, len); }
// Try to send packet over network static int sys_net_try_send(char *data, int len) { if ((uintptr_t)data >= UTOP) { return -E_INVAL; } return e1000_transmit(data, len); }
static int e1000_txpoll(struct net_driver_s *dev) { struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private; int tail = e1000->tx_ring.tail; /* If the polling resulted in data that should be sent out on the network, * the field d_len is set to a value > 0. */ if (e1000->netdev.d_len > 0) { /* Look up the destination MAC address and add it to the Ethernet * header. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (IFF_IS_IPv4(e1000->netdev.d_flags)) #endif { arp_out(&e1000->netdev); } #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif { neighbor_out(&e1000->netdev); } #endif /* CONFIG_NET_IPv6 */ /* Send the packet */ e1000_transmit(e1000); /* Check if there is room in the device to hold another packet. If not, * return a non-zero value to terminate the poll. */ if (!e1000->tx_ring.desc[tail].desc_status) { return -1; } } /* If zero is returned, the polling will continue until all connections have * been examined. */ return 0; }
// // Transmit packet data pointed to by pkt to the e1000 network controller. // If the e1000 has no more space in the transmission buffer, sys_e1000_transmit // will yield the CPU and try later, much like the loop in ipc_send(). // If after 20 tries the packet cannot be transmitted, return -E_E1000_TXBUF_FULL. // // Returns 0 on succes, -E_BAD_ENV if the envid doesn't exist and -E_E1000_TXBUF_FULL // if after 20 retries the packet still cannot be sent. // static int sys_e1000_transmit(envid_t envid, char *pkt, size_t length) { struct Env *env; if (envid2env(envid, &env, 0) != 0) return -E_BAD_ENV; user_mem_assert(env, pkt, length, PTE_W); int num_tries = 20; while((e1000_transmit(pkt, length) == -1) && (num_tries > 0)) { sys_yield(); num_tries--; } if (num_tries == 0) return -E_E1000_TXBUF_FULL; return 0; }
static void e1000_receive(struct e1000_dev *e1000) { int head = e1000->rx_ring.head; unsigned char *cp = (unsigned char *) (e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); int cnt; while (e1000->rx_ring.desc[head].desc_status) { /* Check for errors and update statistics */ // Here we do not handle packets that exceed packet-buffer size if ((e1000->rx_ring.desc[head].desc_status & 3) == 1) { cprintf("NIC READ: Oversized packet\n"); goto next; } /* Check if the packet is a valid size for the uIP buffer configuration */ // get the number of actual data-bytes in this packet cnt = e1000->rx_ring.desc[head].packet_length; if (cnt > CONFIG_NET_BUFSIZE || cnt < 14) { cprintf("NIC READ: invalid package size\n"); goto next; } /* Copy the data data from the hardware to e1000->uip_dev.d_buf. Set * amount of data in e1000->uip_dev.d_len */ // now we try to copy these data-bytes to the UIP buffer memcpy(e1000->uip_dev.d_buf, cp, cnt); e1000->uip_dev.d_len = cnt; /* We only accept IP packets of the configured type and ARP packets */ #ifdef CONFIG_NET_IPv6 if (BUF->type == HTONS(UIP_ETHTYPE_IP6)) #else if (BUF->type == HTONS(UIP_ETHTYPE_IP)) #endif { uip_arp_ipin(&e1000->uip_dev); uip_input(&e1000->uip_dev); /* If the above function invocation resulted in data that should be * sent out on the network, the field d_len will set to a value > 0. */ if (e1000->uip_dev.d_len > 0) { uip_arp_out(&e1000->uip_dev); e1000_transmit(e1000); } } else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(&e1000->uip_dev); /* If the above function invocation resulted in data that should be * sent out on the network, the field d_len will set to a value > 0. */ if (e1000->uip_dev.d_len > 0) { e1000_transmit(e1000); } } next: e1000->rx_ring.desc[head].desc_status = 0; e1000->rx_ring.head = (head + 1) % CONFIG_E1000_N_RX_DESC; e1000->rx_ring.free++; head = e1000->rx_ring.head; cp = (unsigned char *)(e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); } }
static void e1000_receive(struct e1000_dev *e1000) { int head = e1000->rx_ring.head; unsigned char *cp = (unsigned char *) (e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); int cnt; while (e1000->rx_ring.desc[head].desc_status) { /* Check for errors and update statistics */ /* Here we do not handle packets that exceed packet-buffer size */ if ((e1000->rx_ring.desc[head].desc_status & 3) == 1) { cprintf("NIC READ: Oversized packet\n"); goto next; } /* Check if the packet is a valid size for the uIP buffer configuration */ /* get the number of actual data-bytes in this packet */ cnt = e1000->rx_ring.desc[head].packet_length; if (cnt > CONFIG_NET_ETH_MTU || cnt < 14) { cprintf("NIC READ: invalid package size\n"); goto next; } /* Copy the data data from the hardware to e1000->netdev.d_buf. Set * amount of data in e1000->netdev.d_len */ /* now we try to copy these data-bytes to the UIP buffer */ memcpy(e1000->netdev.d_buf, cp, cnt); e1000->netdev.d_len = cnt; #ifdef CONFIG_NET_PKT /* When packet sockets are enabled, feed the frame into the packet tap */ pkt_input(&e1000->netdev); #endif /* We only accept IP packets of the configured type and ARP packets */ #ifdef CONFIG_NET_IPv4 if (BUF->type == HTONS(ETHTYPE_IP)) { nllvdbg("IPv4 frame\n"); /* Handle ARP on input then give the IPv4 packet to the network * layer */ arp_ipin(&e1000->netdev); ipv4_input(&e1000->netdev); /* If the above function invocation resulted in data that should be * sent out on the network, the field d_len will set to a value > 0. */ if (e1000->netdev.d_len > 0) { /* Update the Ethernet header with the correct MAC address */ #ifdef CONFIG_NET_IPv6 if (IFF_IS_IPv4(e1000->netdev.d_flags)) #endif { arp_out(&e1000->netdev); } #ifdef CONFIG_NET_IPv6 else { neighbor_out(&e1000->netdev); } #endif /* And send the packet */ e1000_transmit(e1000); } } else #endif #ifdef CONFIG_NET_IPv6 if (BUF->type == HTONS(ETHTYPE_IP6)) { nllvdbg("Iv6 frame\n"); /* Give the IPv6 packet to the network layer */ ipv6_input(&e1000->netdev); /* If the above function invocation resulted in data that should be * sent out on the network, the field d_len will set to a value > 0. */ if (e1000->netdev.d_len > 0) { /* Update the Ethernet header with the correct MAC address */ #ifdef CONFIG_NET_IPv4 if (IFF_IS_IPv4(e1000->netdev.d_flags)) { arp_out(&e1000->netdev); } else #endif #ifdef CONFIG_NET_IPv6 { neighbor_out(&e1000->netdev); } #endif /* And send the packet */ e1000_transmit(e1000); } } else #endif #ifdef CONFIG_NET_ARP if (BUF->type == htons(ETHTYPE_ARP)) { arp_arpin(&e1000->netdev); /* If the above function invocation resulted in data that should be * sent out on the network, the field d_len will set to a value > 0. */ if (e1000->netdev.d_len > 0) { e1000_transmit(e1000); } #endif } next: e1000->rx_ring.desc[head].desc_status = 0; e1000->rx_ring.head = (head + 1) % CONFIG_E1000_N_RX_DESC; e1000->rx_ring.free++; head = e1000->rx_ring.head; cp = (unsigned char *)(e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE); } }