153 lines
3.4 KiB
C
153 lines
3.4 KiB
C
/*
|
|
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* This document is the property of Apple Computer, Inc.
|
|
* It is considered confidential and proprietary.
|
|
*
|
|
* This document may not be reproduced or transmitted in any form,
|
|
* in whole or in part, without the express written permission of
|
|
* Apple Computer, Inc.
|
|
*/
|
|
//a very minimal Ethernet stack.
|
|
//protocol handlers can register for a certain service, and this layer will call their functions when a packet of that type arrive
|
|
#include <debug.h>
|
|
#include <stdint.h>
|
|
#include <sys.h>
|
|
#include <sys/callout.h>
|
|
#include <lib/net/xp.h>
|
|
#include <lib/net/callbacks.h>
|
|
#include <lib/net/ethernet.h>
|
|
|
|
//For the different layers
|
|
#include <lib/net/arp.h>
|
|
#include <lib/net/ipv4.h>
|
|
#include <lib/net/udp.h>
|
|
#include <lib/net/icmp.h>
|
|
|
|
|
|
static callbacks_t ethercb;
|
|
|
|
int registerEtherTypeHandler(int ethertype,callback_handler cb)
|
|
{
|
|
return registerCallback(ðercb,ethertype,cb);
|
|
}
|
|
|
|
int unregisterEtherTypeHandler(int id)
|
|
{
|
|
return unregisterCallback(ðercb,id);
|
|
}
|
|
|
|
|
|
static int parseEtherHeader(char *buff,int len,uint16_t *ethertype)
|
|
{
|
|
|
|
//XXX: Check that the destination macaddress matches.
|
|
if(ethertype) {
|
|
*ethertype = ntohs(*(uint16_t *)(buff+12));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ethernet_init(void)
|
|
{
|
|
}
|
|
|
|
void ethernet_uninit(void)
|
|
{
|
|
}
|
|
|
|
void ethernet_input(mymbuf_t *inputbuf)
|
|
{
|
|
uint16_t ethertype;
|
|
int len;
|
|
char *rawbuf;
|
|
callback_handler cb;
|
|
|
|
len = mbuf_getlength(inputbuf);
|
|
rawbuf = mbuf_getlinear(inputbuf);
|
|
//This fails if the packet was not directed to us (ie, wrong macaddr)
|
|
if(parseEtherHeader(rawbuf,len,ðertype) == 0) {
|
|
cb = find_callback(ðercb,ethertype);
|
|
if(cb) {
|
|
cb(rawbuf,ETHERNET_OFFSET,len,0);
|
|
} else {
|
|
// printf("Unsupported ethertype 0x%x\n",ethertype);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
//Called from timer (background) or from tsys commandprompt if not background
|
|
//Handles maxpkt packages before returning. (Or until it would have to block)
|
|
void ethernet_workloop(struct callout *c, void *param)
|
|
{
|
|
int i;
|
|
uint16_t ethertype;
|
|
int len;
|
|
char *rawbuf;
|
|
callback_handler cb;
|
|
int maxpkt = (int)param;
|
|
// utime_t now;
|
|
//
|
|
|
|
callout_reset(c, 0);
|
|
|
|
if(!buf)
|
|
return;
|
|
|
|
for(i = 0;i<maxpkt;i++) {
|
|
// now = system_time();
|
|
mbuf_setlength(buf,0);
|
|
mbuf_setoffset(buf,0);
|
|
if(xp_get_packet(buf)) {
|
|
len = mbuf_getlength(buf);
|
|
rawbuf = mbuf_getlinear(buf);
|
|
//This fails if the packet was not directed to us (ie, wrong macaddr)
|
|
if(parseEtherHeader(rawbuf,len,ðertype) == 0) {
|
|
cb = find_callback(ðercb,ethertype);
|
|
if(cb) {
|
|
cb(rawbuf,ETHERNET_OFFSET,len,0);
|
|
} else {
|
|
// printf("Unsupported ethertype 0x%x\n",ethertype);
|
|
}
|
|
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
// now = system_time() - now;
|
|
// printf("a package took %ld usec\n",now);
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
int add_eth_and_transmit(mymbuf_t *buffer,char *macaddrto,int ethertype)
|
|
{
|
|
char *ethernethead;
|
|
// utime_t perftime = system_time();
|
|
|
|
ethernethead = mbuf_head(buffer,14);
|
|
if(!ethernethead) {
|
|
dprintf(DEBUG_INFO, "Ethernetheader: Not enough space in mbuf.\n");
|
|
return -1;
|
|
}
|
|
|
|
memcpy(ethernethead,macaddrto,6);
|
|
xp_getmac((uint8_t*)ðernethead[6]);
|
|
*(uint16_t *)ðernethead[12] = htons(ethertype);
|
|
/*
|
|
tailcrc = mbuf_tail(buffer,4);
|
|
|
|
//XXX: Calculate CRC
|
|
printf("Calculate CRC!\n");
|
|
*/ // Is done by our ethernet driver...
|
|
return xp_transmit_packet(buffer);
|
|
// printf("transmit took %ld usec\n", system_time() - perftime);
|
|
}
|
|
|
|
|
|
|
|
|