summaryrefslogtreecommitdiffstats
path: root/src/core/nic.c
diff options
context:
space:
mode:
authorMichael Brown2005-04-12 18:52:59 +0200
committerMichael Brown2005-04-12 18:52:59 +0200
commit1434e8d68dcf83a46460506a10cecc73ba00fa0b (patch)
treeef99f27d5f8320d137b05c8a575f02eb03640e50 /src/core/nic.c
parentNeeds to be updated to new probe logic. (diff)
downloadipxe-1434e8d68dcf83a46460506a10cecc73ba00fa0b.tar.gz
ipxe-1434e8d68dcf83a46460506a10cecc73ba00fa0b.tar.xz
ipxe-1434e8d68dcf83a46460506a10cecc73ba00fa0b.zip
struct nic is now part of struct dev, rather than the other way around.
Tie into new boot device framework.
Diffstat (limited to 'src/core/nic.c')
-rw-r--r--src/core/nic.c198
1 files changed, 87 insertions, 111 deletions
diff --git a/src/core/nic.c b/src/core/nic.c
index 44f80c356..2cda9e8e7 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)) {