Index: redboot/current/ChangeLog =================================================================== RCS file: /home/cvs/ecc/ecc/redboot/current/ChangeLog,v retrieving revision 1.81 diff -u -5 -p -r1.81 ChangeLog --- redboot/current/ChangeLog 2001/01/30 15:27:17 1.81 +++ redboot/current/ChangeLog 2001/01/31 12:23:04 @@ -1,5 +1,12 @@ +2001-01-31 Grant Edwards + + * include/net/net.h: + * src/net/enet.c (__eth_install_listener, __eth_remove_listener): + New functions - allow user registerable callout to handle + non-standard ethernet packets. + 2001-01-30 Gary Thomas * src/main.c (do_reset): HAL macro name changed. * src/net/ping.c (do_ping): Remove warning. @@ -360,11 +367,11 @@ * src/main.c (cyg_start): Change to use struct init_tab_entry per above 2000-09-07 Andrew Lunn * src/load.c, include/redboot.h: renamed the getc functions to - redboot_getc and made them globel so custom boot loaders can use + redboot_getc and made them global so custom boot loaders can use them. 2000-09-06 Gary Thomas * doc/users_guide: Add info about region locking/unlocking. Index: redboot/current/include/net/net.h =================================================================== RCS file: /home/cvs/ecc/ecc/redboot/current/include/net/net.h,v retrieving revision 1.6 diff -u -5 -p -r1.6 net.h --- redboot/current/include/net/net.h 2001/01/22 18:52:20 1.6 +++ redboot/current/include/net/net.h 2001/01/31 11:34:44 @@ -278,11 +278,11 @@ typedef struct _pktbuf { word *buf; } pktbuf_t; /* protocol handler */ -typedef void (*pkt_handler_t)(pktbuf_t *pkt); +typedef void (*pkt_handler_t)(pktbuf_t *pkt, eth_header_t *eth_hdr); /* ICMP fielder */ typedef void (*icmp_handler_t)(pktbuf_t *pkt, ip_route_t *src_route); typedef struct _udp_socket { @@ -375,12 +375,14 @@ extern void __pktbuf_dump(void); /* * Install handlers for ethernet packets. * Returns old handler. */ -extern pkt_handler_t __eth_install_handler(int eth_type, - pkt_handler_t handler); +extern pkt_handler_t __eth_install_listener(int eth_type, + pkt_handler_t handler); +extern void __eth_remove_listener(int eth_type); + /* * Set tcp port number for debugging. If not called, a default * will be selected. */ extern void _bsp_net_set_debug_port(int portnum); Index: redboot/current/src/net/enet.c =================================================================== RCS file: /home/cvs/ecc/ecc/redboot/current/src/net/enet.c,v retrieving revision 1.5 diff -u -5 -p -r1.5 enet.c --- redboot/current/src/net/enet.c 2000/10/30 13:50:27 1.5 +++ redboot/current/src/net/enet.c 2001/01/31 11:34:44 @@ -21,11 +21,11 @@ // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### //========================================================================== @@ -57,19 +57,69 @@ static int num_rarp = 0; #endif static int num_received = 0; static int num_transmitted = 0; #endif +// +// Support for user handlers of additional ethernet packets (nonIP) +// + +#define NUM_EXTRA_HANDLERS 4 +static struct { + int type; + pkt_handler_t handler; +} eth_handlers[NUM_EXTRA_HANDLERS]; + +pkt_handler_t +__eth_install_listener(int eth_type, pkt_handler_t handler) +{ + int i, empty; + pkt_handler_t old; + + empty = -1; + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == eth_type) { + // Replace existing handler + old = eth_handlers[i].handler; + eth_handlers[i].handler = handler; + return old; + } + if (eth_handlers[i].type == 0) { + empty = i; + } + } + if (empty >= 0) { + // Found a free slot + eth_handlers[empty].type = eth_type; + eth_handlers[empty].handler = handler; + } + printf("** Warning: can't install listener for ethernet type 0x%02x\n", eth_type); + return (pkt_handler_t)0; +} + +void +__eth_remove_listener(int eth_type) +{ + int i; + + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == eth_type) { + eth_handlers[i].type = 0; + } + } +} + /* * Non-blocking poll of ethernet link. Process packets until no more * are available. */ void __enet_poll(void) { pktbuf_t *pkt; eth_header_t eth_hdr; + int i, type; while (true) { /* * Try to get a free pktbuf and return if none * are available. @@ -84,11 +134,11 @@ __enet_poll(void) if ((pkt->pkt_bytes = eth_drv_read((char *)ð_hdr, (char *)pkt->buf, ETH_MAX_PKTLEN)) > 0) { #if ENET_STATS ++num_received; #endif - switch (ntohs(eth_hdr.type)) { + switch (type = ntohs(eth_hdr.type)) { case ETH_TYPE_IP: #if ENET_STATS ++num_ip; #endif @@ -113,10 +163,15 @@ __enet_poll(void) __rarp_handler(pkt); break; #endif default: + for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { + if (eth_handlers[i].type == type) { + (eth_handlers[i].handler)(pkt, ð_hdr); + } + } __pktbuf_free(pkt); break; } } else { __pktbuf_free(pkt); @@ -143,11 +198,10 @@ __enet_send(pktbuf_t *pkt, enet_addr_t * eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes); #if ENET_STATS ++num_transmitted; #endif } - #ifdef __LITTLE_ENDIAN__ unsigned long ntohl(unsigned long x)