I have finally managed to bring it to a pingable state!
So in case someone else wants to try this at home...
I took SPI read/write functions from the Integrating Wiznet W5100, WIZ811MJ network module with Atmel AVR Microcontroller | ermicroblog mentioned above,
and the init part is what I gather from the library files.
The way I compiled upload this is :
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega2560 -c -o $1.o $1.c
avr-gcc -mmcu=atmega2560 $1.o -o $1
avr-objcopy -O ihex -R .eeprom $1 $1.hex
avrdude -F -V -c arduino -p m2560 -c avrispmkII -P /dev/ttyACM0 -U flash:w:$1.hex
#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_CS PORTB4
#define MAX_SOCK_NUM 4
#define TXBUF_BASE 0x4000
#define RXBUF_BASE 0x6000
// Wiznet W5100 Op Code
#define WIZNET_WRITE_OPCODE 0xF0
#define WIZNET_READ_OPCODE 0x0F
// Wiznet W5100 Register Addresses
#define MR 0x0000 // Mode Register
#define GAR 0x0001 // Gateway Address: 0x0001 to 0x0004
#define SUBR 0x0005 // Subnet mask Address: 0x0005 to 0x0008
#define SAR 0x0009 // Source Hardware Address (MAC): 0x0009 to 0x000E
#define SIPR 0x000F // Source IP Address: 0x000F to 0x0012
#define RMSR 0x001A // RX Memory Size Register
#define TMSR 0x001B // TX Memory Size Register
void SPI_Write(unsigned int addr,unsigned char data)
{
// Activate the CS pin
SPI_PORT &= ~(1<<SPI_CS);
// Start Wiznet W5100 Write OpCode transmission
SPDR = WIZNET_WRITE_OPCODE;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address High Bytes transmission
SPDR = (addr & 0xFF00) >> 8;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address Low Bytes transmission
SPDR = addr & 0x00FF;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Data transmission
SPDR = data;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// CS pin is not active
SPI_PORT |= (1<<SPI_CS);
}
unsigned char SPI_Read(unsigned int addr)
{
// Activate the CS pin
SPI_PORT &= ~(1<<SPI_CS);
// Start Wiznet W5100 Read OpCode transmission
SPDR = WIZNET_READ_OPCODE;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address High Bytes transmission
SPDR = (addr & 0xFF00) >> 8;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Start Wiznet W5100 Address Low Bytes transmission
SPDR = addr & 0x00FF;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// Send Dummy transmission for reading the data
SPDR = 0x00;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
// CS pin is not active
SPI_PORT |= (1<<SPI_CS);
return(SPDR);
}
unsigned char mac_addr[] = {0x00,0x16,0x36,0xDE,0x58,0xF7};
unsigned char ip_addr[] = {192,168,88,10};
unsigned char sub_mask[] = {255,255,255,0};
unsigned char gtw_addr[] = {192,168,88,1};
int main(){
SPI_DDR = (1<<PORTB2)|(1<<PORTB1)|(1<<PORTB0);
// CS pin is not active
SPI_PORT |= (1<<SPI_CS);
// Enable SPI, Master Mode 0, set the clock rate fck/2
SPCR = (1<<SPE)|(1<<MSTR);
SPSR |= (1<<SPI2X);
DDRB |= _BV(4);
SPI_Write(MR,0b10000000);
SPI_Write(TMSR,0x55);
SPI_Write(RMSR,0x55);
static const uint16_t SSIZE = 2048; // Max Tx buffer size
static const uint16_t RSIZE = 2048; // Max Rx buffer size
uint16_t SBASE[4]; // Tx buffer base address
uint16_t RBASE[4];
SBASE[0] = TXBUF_BASE + SSIZE * 0;
RBASE[0] = RXBUF_BASE + RSIZE * 0;
SBASE[1] = TXBUF_BASE + SSIZE * 1;
RBASE[1] = RXBUF_BASE + RSIZE * 1;
SBASE[2] = TXBUF_BASE + SSIZE * 2;
RBASE[2] = RXBUF_BASE + RSIZE * 2;
SBASE[3] = TXBUF_BASE + SSIZE * 3;
RBASE[3] = RXBUF_BASE + RSIZE * 3;
SPI_Write(SIPR + 0,ip_addr[0]);
SPI_Write(SIPR + 1,ip_addr[1]);
SPI_Write(SIPR + 2,ip_addr[2]);
SPI_Write(SIPR + 3,ip_addr[3]);
SPI_Write(SUBR + 0,sub_mask[0]);
SPI_Write(SUBR + 1,sub_mask[1]);
SPI_Write(SUBR + 2,sub_mask[2]);
SPI_Write(SUBR + 3,sub_mask[3]);
SPI_Write(SAR + 0,mac_addr[0]);
SPI_Write(SAR + 1,mac_addr[1]);
SPI_Write(SAR + 2,mac_addr[2]);
SPI_Write(SAR + 3,mac_addr[3]);
SPI_Write(SAR + 4,mac_addr[4]);
SPI_Write(SAR + 5,mac_addr[5]);
SPI_Write(GAR + 0,gtw_addr[0]);
SPI_Write(GAR + 1,gtw_addr[1]);
SPI_Write(GAR + 2,gtw_addr[2]);
SPI_Write(GAR + 3,gtw_addr[3]);
return 0;
}