diff --git a/src/core/nic.c b/src/core/nic.c index 44f80c35..2cda9e8e 100644 --- a/src/core/nic.c +++ b/src/core/nic.c @@ -15,6 +15,8 @@ Literature dealing with the network protocols: **************************************************************************/ #include "etherboot.h" +#include "console.h" +#include "dev.h" #include "nic.h" #include "elf.h" /* FOR EM_CURRENT */ @@ -221,52 +223,6 @@ int vci_etherboot; #endif #endif /* NO_DHCP_SUPPORT */ -static int dummy(void *unused __unused) -{ - return (0); -} - -/* Careful. We need an aligned buffer to avoid problems on machines - * that care about alignment. To trivally align the ethernet data - * (the ip hdr and arp requests) we offset the packet by 2 bytes. - * leaving the ethernet data 16 byte aligned. Beyond this - * we use memmove but this makes the common cast simple and fast. - */ -static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned; - -struct nic nic = -{ - { - 0, /* dev.disable */ - { - 0, - 0, - PCI_BUS_TYPE, - }, /* dev.devid */ - 0, /* index */ - 0, /* type */ - PROBE_FIRST, /* how_pobe */ - PROBE_NONE, /* to_probe */ - 0, /* failsafe */ - 0, /* type_index */ - {}, /* state */ - }, - (int (*)(struct nic *, int))dummy, /* poll */ - (void (*)(struct nic *, const char *, - unsigned int, unsigned int, - const char *))dummy, /* transmit */ - (void (*)(struct nic *, - irq_action_t))dummy, /* irq */ - 0, /* flags */ - &rom, /* rom_info */ - arptable[ARP_CLIENT].node, /* node_addr */ - packet + ETH_DATA_ALIGN, /* packet */ - 0, /* packetlen */ - 0, /* ioaddr */ - 0, /* irqno */ - 0, /* priv_data */ -}; - #ifdef RARP_NOT_BOOTP static int rarp(void); #else @@ -275,42 +231,12 @@ static int bootp(void); static unsigned short tcpudpchksum(struct iphdr *ip); -int eth_probe(struct dev *dev) -{ - return probe(dev); -} - -int eth_poll(int retrieve) -{ - return ((*nic.poll)(&nic, retrieve)); -} - -void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p) -{ - (*nic.transmit)(&nic, d, t, s, p); - if (t == ETH_P_IP) twiddle(); -} - -void eth_disable(void) -{ -#ifdef MULTICAST_LEVEL2 - int i; - for(i = 0; i < MAX_IGMP; i++) { - leave_group(i); - } -#endif - disable(&nic.dev); -} - -void eth_irq (irq_action_t action) -{ - (*nic.irq)(&nic,action); -} +struct nic *nic = &dev.nic; /* * Find out what our boot parameters are */ -int eth_load_configuration(struct dev *dev __unused) +static int nic_load_configuration(struct dev *dev __unused) { int server_found; /* Find a server to get BOOTP reply from */ @@ -340,7 +266,7 @@ int eth_load_configuration(struct dev *dev __unused) /************************************************************************** LOAD - Try to get booted **************************************************************************/ -int eth_load(struct dev *dev __unused) +static int nic_load(struct dev *dev __unused) { const char *kernel; printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr ); @@ -390,6 +316,56 @@ int eth_load(struct dev *dev __unused) } +static void nic_disable ( struct dev *dev ) { + struct nic *nic = &dev->nic; + +#ifdef MULTICAST_LEVEL2 + int i; + for(i = 0; i < MAX_IGMP; i++) { + leave_group(i); + } +#endif + + nic->nic_op->disable ( nic ); +} + +/* + * Device operations tables + * + */ +static struct dev_operations nic_operations = { + .disable = nic_disable, + .load_configuration = nic_load_configuration, + .load = nic_load, +}; + +/* Careful. We need an aligned buffer to avoid problems on machines + * that care about alignment. To trivally align the ethernet data + * (the ip hdr and arp requests) we offset the packet by 2 bytes. + * leaving the ethernet data 16 byte aligned. Beyond this + * we use memmove but this makes the common cast simple and fast. + */ +static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned; + +/* + * Set up a struct dev to operate as a NIC, return the struct nic * + * + */ +struct nic * nic_device ( struct dev *dev ) { + struct nic *nic = &dev->nic; + + memset ( nic, 0, sizeof ( *nic ) ); + nic->node_addr = arptable[ARP_CLIENT].node; + nic->packet = packet + ETH_DATA_ALIGN; + dev->dev_op = &nic_operations; + return nic; +} + + + + + + /************************************************************************** DEFAULT_NETMASK - Return default netmask for IP address **************************************************************************/ @@ -414,9 +390,9 @@ static int await_arp(int ival, void *ptr, struct arprequest *arpreply; if (ptype != ETH_P_ARP) return 0; - if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest)) + if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest)) return 0; - arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; + arpreply = (struct arprequest *)&nic->packet[ETH_HLEN]; if (arpreply->opcode != htons(ARP_REPLY)) return 0; @@ -703,7 +679,7 @@ int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block ) continue; /* Back to waiting for packet */ } /* Packet has been received */ - rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN]; + rcvd = (struct tftp_t *)&nic->packet[ETH_HLEN]; recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr) - sizeof(rcvd->opcode); rport = ntohs(rcvd->udp.src); @@ -783,9 +759,9 @@ static int await_rarp(int ival, void *ptr, struct arprequest *arpreply; if (ptype != ETH_P_RARP) return 0; - if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest)) + if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest)) return 0; - arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; + arpreply = (struct arprequest *)&nic->packet[ETH_HLEN]; if (arpreply->opcode != htons(RARP_REPLY)) return 0; if ((arpreply->opcode == htons(RARP_REPLY)) && @@ -847,9 +823,9 @@ static int await_bootp(int ival __unused, void *ptr __unused, if (!udp) { return 0; } - bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN + + bootpreply = (struct bootp_t *)&nic->packet[ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr)]; - if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) + + if (nic->packetlen < ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + #ifdef NO_DHCP_SUPPORT sizeof(struct bootp_t) @@ -922,11 +898,11 @@ static int bootp(void) unsigned char *bp_vend; #ifndef NO_DHCP_SUPPORT - dhcp_machine_info[4] = nic.dev.devid.bus_type; - dhcp_machine_info[5] = nic.dev.devid.vendor_id & 0xff; - dhcp_machine_info[6] = ((nic.dev.devid.vendor_id) >> 8) & 0xff; - dhcp_machine_info[7] = nic.dev.devid.device_id & 0xff; - dhcp_machine_info[8] = ((nic.dev.devid.device_id) >> 8) & 0xff; + dhcp_machine_info[4] = dev.devid.bus_type; + dhcp_machine_info[5] = dev.devid.vendor_id & 0xff; + dhcp_machine_info[6] = ((dev.devid.vendor_id) >> 8) & 0xff; + dhcp_machine_info[7] = dev.devid.device_id & 0xff; + dhcp_machine_info[8] = ((dev.devid.device_id) >> 8) & 0xff; #endif /* NO_DHCP_SUPPORT */ memset(&ip, 0, sizeof(struct bootpip_t)); ip.bp.bp_op = BOOTP_REQUEST; @@ -1092,11 +1068,11 @@ static void process_igmp(struct iphdr *ip, unsigned long now) int i; unsigned iplen; if (!ip || (ip->protocol == IP_IGMP) || - (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) { + (nic->packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) { return; } iplen = (ip->verhdrlen & 0xf)*4; - igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)]; + igmp = (struct igmp *)&nic->packet[sizeof(struct iphdr)]; if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0) return; if ((igmp->type == IGMP_QUERY) && @@ -1303,7 +1279,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr, syn_ack = state == CLOSED || state == SYN_RCVD; consumed = ntohl(tcp->ack) - send_seq - syn_ack; if (consumed < 0 || consumed > can_send) { - tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]); + tcp_reset((struct iphdr *)&nic->packet[ETH_HLEN]); goto recv_data; } @@ -1345,7 +1321,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr, } consume_data: - ip = (struct iphdr *)&nic.packet[ETH_HLEN]; + ip = (struct iphdr *)&nic->packet[ETH_HLEN]; header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C); payload = ntohs(ip->len) - header_size; if (payload > 0 && state == ESTABLISHED) { @@ -1354,7 +1330,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr, recv_seq += payload - old_bytes; if (state != FIN_WAIT_1 && state != FIN_WAIT_2 && !recv(payload - old_bytes, - &nic.packet[ETH_HLEN+header_size+old_bytes], + &nic->packet[ETH_HLEN+header_size+old_bytes], ptr)) { goto close; } @@ -1466,15 +1442,15 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) /* We have something! */ /* Find the Ethernet packet type */ - if (nic.packetlen >= ETH_HLEN) { - ptype = ((unsigned short) nic.packet[12]) << 8 - | ((unsigned short) nic.packet[13]); + if (nic->packetlen >= ETH_HLEN) { + ptype = ((unsigned short) nic->packet[12]) << 8 + | ((unsigned short) nic->packet[13]); } else continue; /* what else could we do with it? */ /* Verify an IP header */ ip = 0; - if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) { + if ((ptype == ETH_P_IP) && (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr))) { unsigned ipoptlen; - ip = (struct iphdr *)&nic.packet[ETH_HLEN]; + ip = (struct iphdr *)&nic->packet[ETH_HLEN]; if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F)) continue; iplen = (ip->verhdrlen & 0xf) * 4; @@ -1496,17 +1472,17 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) /* Delete the ip options, to guarantee * good alignment, and make etherboot simpler. */ - memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)], - &nic.packet[ETH_HLEN + iplen], - nic.packetlen - ipoptlen); - nic.packetlen -= ipoptlen; + memmove(&nic->packet[ETH_HLEN + sizeof(struct iphdr)], + &nic->packet[ETH_HLEN + iplen], + nic->packetlen - ipoptlen); + nic->packetlen -= ipoptlen; } } udp = 0; if (ip && (ip->protocol == IP_UDP) && - (nic.packetlen >= + (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) { - udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)]; + udp = (struct udphdr *)&nic->packet[ETH_HLEN + sizeof(struct iphdr)]; /* Make certain we have a reasonable packet length */ if (ntohs(udp->len) > (ntohs(ip->len) - iplen)) @@ -1520,9 +1496,9 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) tcp = 0; #ifdef DOWNLOAD_PROTO_HTTP if (ip && (ip->protocol == IP_TCP) && - (nic.packetlen >= + (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){ - tcp = (struct tcphdr *)&nic.packet[ETH_HLEN + + tcp = (struct tcphdr *)&nic->packet[ETH_HLEN + sizeof(struct iphdr)]; /* Make certain we have a reasonable packet length */ if (((ntohs(tcp->ctrl) >> 10) & 0x3C) > @@ -1544,11 +1520,11 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) * action. This allows us reply to arp, igmp, and lacp queries. */ if ((ptype == ETH_P_ARP) && - (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) { + (nic->packetlen >= ETH_HLEN + sizeof(struct arprequest))) { struct arprequest *arpreply; unsigned long tmp; - arpreply = (struct arprequest *)&nic.packet[ETH_HLEN]; + arpreply = (struct arprequest *)&nic->packet[ETH_HLEN]; memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); if ((arpreply->opcode == htons(ARP_REQUEST)) && (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {