osd-contiki/cpu/6502/net/ethernet.c
Oliver Schmidt a5d7a06027 Enhanced Ethernet drivers.
Made Ethernet drivers easier to consume by assembly programs.
* Replaced function pointers with JMP instructions.
* Provide return values additionally via Carry flag.

Reset Ethernet chips on initialization.
Both for the CS8900A and the W5100 the data sheets just say that
the RESET bit is automatically cleared after the RESET. This may
be interpreted in two ways:
1) There's no need to be afraid of reading the RESET bit as 1 and
unintentionally trigger a RESET by writing it back after ORing in
some other bit.
2) The RESET process isn't complete before the RESET bit hasn't
become 0 again.
It's impossible for me to empirically falsify the latter option
as the drivers are supposed to work on faster machines than the
ones I have access to. And if the RESET process includes things
like oscillators then the time to complete the RESET could differ
even between multiple exemplars of the same chip. Therefore I
opted to presume the latter option.
However that means a non-exsistent chip may cause an infinite
loop while waiting for the RESET bit to be cleared so I finally
added code to detect the presence of the Ethernet chips. There's
a risk of a chip being locked up in a way that makes the detection
fail - and therefore the RESET not being performed. This catch-22
needs to be solved by the user doing a hard RESET.
2014-06-12 22:56:35 +02:00

134 lines
4 KiB
C

/*
* Copyright (c) 2007, Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Oliver Schmidt <ol.sc@web.de>
*
*/
#include <modload.h>
#include "contiki-net.h"
#include "cfs/cfs.h"
#include "sys/log.h"
#include "lib/error.h"
#include "net/ethernet-drv.h"
#include "net/ethernet.h"
struct {
char signature[4];
struct uip_eth_addr ethernet_address;
uint8_t *buffer;
uint16_t buffer_size;
char jmp_init;
char __fastcall__ (* init)(uint16_t reg);
char jmp_poll;
uint16_t (* poll)(void);
char jmp_send;
void __fastcall__ (* send)(uint16_t len);
char jmp_exit;
void (* exit)(void);
} *module;
/*---------------------------------------------------------------------------*/
void CC_FASTCALL
ethernet_init(struct ethernet_config *config)
{
static const char signature[4] = {0x65, 0x74, 0x68, 0x01};
#ifndef ETHERNET
struct mod_ctrl module_control = {cfs_read};
uint8_t byte;
module_control.callerdata = cfs_open(config->name, CFS_READ);
if(module_control.callerdata < 0) {
log_message(config->name, ": File not found");
error_exit();
}
byte = mod_load(&module_control);
if(byte != MLOAD_OK) {
log_message(config->name, byte == MLOAD_ERR_MEM? ": Out of memory":
": No module");
error_exit();
}
cfs_close(module_control.callerdata);
module = module_control.module;
for(byte = 0; byte < 4; ++byte) {
if(module->signature[byte] != signature[byte]) {
log_message(config->name, ": No ETH driver");
error_exit();
}
}
#else /* !ETHERNET */
extern void ETHERNET;
module = &ETHERNET;
#endif /* !ETHERNET */
module->buffer = uip_buf;
module->buffer_size = UIP_BUFSIZE;
if(module->init(config->addr)) {
log_message(config->name, ": No hardware");
error_exit();
}
uip_setethaddr(module->ethernet_address);
}
/*---------------------------------------------------------------------------*/
uint16_t
ethernet_poll(void)
{
return module->poll();
}
/*---------------------------------------------------------------------------*/
void
ethernet_send(void)
{
module->send(uip_len);
}
/*---------------------------------------------------------------------------*/
void
ethernet_exit(void)
{
module->exit();
#ifndef ETHERNET
mod_free(module);
#endif /* !ETHERNET */
}
/*---------------------------------------------------------------------------*/