Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 5 commits
  • 16 files changed
  • 0 comments
  • 1 contributor
5  milkymist/minimac3/__init__.py
@@ -26,7 +26,8 @@ def __init__(self, address):
26 26
 		self._rx_count_0 = RegisterField("rx_count_0", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
27 27
 		self._rx_count_1 = RegisterField("rx_count_1", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
28 28
 		self._tx_count = RegisterField("tx_count", _count_width, access_dev=READ_WRITE)
29  
-		regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count]
  29
+		self._tx_start = RegisterField("tx_start", access_bus=WRITE_ONLY)
  30
+		regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count, self._tx_start]
30 31
 		
31 32
 		self._rx_event_0 = EventSourcePulse()
32 33
 		self._rx_event_1 = EventSourcePulse()
@@ -78,7 +79,7 @@ def get_fragment(self):
78 79
 					("rx_ready_0", rx_ready_0),
79 80
 					("rx_ready_1", rx_ready_1),
80 81
 					
81  
-					("tx_start", self._tx_count.re),
  82
+					("tx_start", self._tx_start.re),
82 83
 					("tx_count", self._tx_count.field.r),
83 84
 					
84 85
 					("wb_adr_i", self.membus.adr),
2  software/bios/Makefile
... ...
@@ -1,7 +1,7 @@
1 1
 M2DIR=../..
2 2
 include $(M2DIR)/software/include.mak
3 3
 
4  
-OBJECTS=crt0.o isr.o ddrinit.o main.o
  4
+OBJECTS=crt0.o isr.o ddrinit.o timer.o main.o microudp.o tftp.o boot-helper.o boot.o
5 5
 
6 6
 all: bios.bin
7 7
 
10  software/bios/boot-helper.S
... ...
@@ -0,0 +1,10 @@
  1
+.section    .text, "ax", @progbits
  2
+.global     boot_helper
  3
+boot_helper:
  4
+	/* Invalidate instruction cache */
  5
+	wcsr ICC, r0
  6
+	nop
  7
+	nop
  8
+	nop
  9
+	nop
  10
+	call r5
284  software/bios/boot.c
... ...
@@ -0,0 +1,284 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdio.h>
  19
+#include <console.h>
  20
+#include <uart.h>
  21
+#include <system.h>
  22
+#include <board.h>
  23
+#include <extra/crc.h>
  24
+#include <sfl.h>
  25
+#include <string.h>
  26
+#include <irq.h>
  27
+
  28
+#include <hw/flash.h>
  29
+#include <hw/mem.h>
  30
+
  31
+#include "timer.h"
  32
+#include "microudp.h"
  33
+#include "tftp.h"
  34
+#include "boot.h"
  35
+
  36
+extern int rescue;
  37
+extern void boot_helper(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr);
  38
+
  39
+static void __attribute__((noreturn)) boot(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr)
  40
+{
  41
+	printf("Executing booted program.\n");
  42
+	uart_sync();
  43
+	irq_setmask(0);
  44
+	irq_setie(0);
  45
+	boot_helper(r1, r2, r3, r4, addr);
  46
+	while(1);
  47
+}
  48
+
  49
+static int check_ack(void)
  50
+{
  51
+	int recognized;
  52
+	static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK;
  53
+
  54
+	timer_enable(0);
  55
+	timer_set_reload(0);
  56
+	timer_set_counter(get_system_frequency()/4);
  57
+	timer_enable(1);
  58
+	recognized = 0;
  59
+	while(timer_get()) {
  60
+		if(uart_read_nonblock()) {
  61
+			char c;
  62
+			c = uart_read();
  63
+			if(c == str[recognized]) {
  64
+				recognized++;
  65
+				if(recognized == SFL_MAGIC_LEN)
  66
+					return 1;
  67
+			} else {
  68
+				if(c == str[0])
  69
+					recognized = 1;
  70
+				else
  71
+					recognized = 0;
  72
+			}
  73
+		}
  74
+	}
  75
+	return 0;
  76
+}
  77
+
  78
+#define MAX_FAILED 5
  79
+
  80
+void serialboot(void)
  81
+{
  82
+	struct sfl_frame frame;
  83
+	int failed;
  84
+	unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
  85
+	static const char str[SFL_MAGIC_LEN+1] = SFL_MAGIC_REQ;
  86
+	const char *c;
  87
+
  88
+	printf("Booting from serial...\n");
  89
+
  90
+	c = str;
  91
+	while(*c) {
  92
+		uart_write(*c);
  93
+		c++;
  94
+	}
  95
+	if(!check_ack()) {
  96
+		printf("Timeout\n");
  97
+		return;
  98
+	}
  99
+
  100
+	failed = 0;
  101
+	cmdline_adr = initrdstart_adr = initrdend_adr = 0;
  102
+	while(1) {
  103
+		int i;
  104
+		int actualcrc;
  105
+		int goodcrc;
  106
+
  107
+		/* Grab one frame */
  108
+		frame.length = uart_read();
  109
+		frame.crc[0] = uart_read();
  110
+		frame.crc[1] = uart_read();
  111
+		frame.cmd = uart_read();
  112
+		for(i=0;i<frame.length;i++)
  113
+			frame.payload[i] = uart_read();
  114
+
  115
+		/* Check CRC */
  116
+		actualcrc = ((int)frame.crc[0] << 8)|(int)frame.crc[1];
  117
+		goodcrc = crc16(&frame.cmd, frame.length+1);
  118
+		if(actualcrc != goodcrc) {
  119
+			failed++;
  120
+			if(failed == MAX_FAILED) {
  121
+				printf("Too many consecutive errors, aborting");
  122
+				return;
  123
+			}
  124
+			uart_write(SFL_ACK_CRCERROR);
  125
+			continue;
  126
+		}
  127
+
  128
+		/* CRC OK */
  129
+		switch(frame.cmd) {
  130
+			case SFL_CMD_ABORT:
  131
+				failed = 0;
  132
+				uart_write(SFL_ACK_SUCCESS);
  133
+				return;
  134
+			case SFL_CMD_LOAD: {
  135
+				char *writepointer;
  136
+
  137
+				failed = 0;
  138
+				writepointer = (char *)(
  139
+					 ((unsigned int)frame.payload[0] << 24)
  140
+					|((unsigned int)frame.payload[1] << 16)
  141
+					|((unsigned int)frame.payload[2] << 8)
  142
+					|((unsigned int)frame.payload[3] << 0));
  143
+				for(i=4;i<frame.length;i++)
  144
+					*(writepointer++) = frame.payload[i];
  145
+				uart_write(SFL_ACK_SUCCESS);
  146
+				break;
  147
+			}
  148
+			case SFL_CMD_JUMP: {
  149
+				unsigned int addr;
  150
+
  151
+				failed = 0;
  152
+				addr =  ((unsigned int)frame.payload[0] << 24)
  153
+					|((unsigned int)frame.payload[1] << 16)
  154
+					|((unsigned int)frame.payload[2] << 8)
  155
+					|((unsigned int)frame.payload[3] << 0);
  156
+				uart_write(SFL_ACK_SUCCESS);
  157
+				boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, addr);
  158
+				break;
  159
+			}
  160
+			case SFL_CMD_CMDLINE:
  161
+				failed = 0;
  162
+				cmdline_adr =  ((unsigned int)frame.payload[0] << 24)
  163
+					      |((unsigned int)frame.payload[1] << 16)
  164
+					      |((unsigned int)frame.payload[2] << 8)
  165
+					      |((unsigned int)frame.payload[3] << 0);
  166
+				uart_write(SFL_ACK_SUCCESS);
  167
+				break;
  168
+			case SFL_CMD_INITRDSTART:
  169
+				failed = 0;
  170
+				initrdstart_adr =  ((unsigned int)frame.payload[0] << 24)
  171
+					          |((unsigned int)frame.payload[1] << 16)
  172
+					          |((unsigned int)frame.payload[2] << 8)
  173
+					          |((unsigned int)frame.payload[3] << 0);
  174
+				uart_write(SFL_ACK_SUCCESS);
  175
+				break;
  176
+			case SFL_CMD_INITRDEND:
  177
+				failed = 0;
  178
+				initrdend_adr =  ((unsigned int)frame.payload[0] << 24)
  179
+					        |((unsigned int)frame.payload[1] << 16)
  180
+					        |((unsigned int)frame.payload[2] << 8)
  181
+					        |((unsigned int)frame.payload[3] << 0);
  182
+				uart_write(SFL_ACK_SUCCESS);
  183
+				break;
  184
+			default:
  185
+				failed++;
  186
+				if(failed == MAX_FAILED) {
  187
+					printf("Too many consecutive errors, aborting");
  188
+					return;
  189
+				}
  190
+				uart_write(SFL_ACK_UNKNOWN);
  191
+				break;
  192
+		}
  193
+	}
  194
+}
  195
+
  196
+#define LOCALIP1 192
  197
+#define LOCALIP2 168
  198
+#define LOCALIP3 0
  199
+#define LOCALIP4 42
  200
+#define REMOTEIP1 192
  201
+#define REMOTEIP2 168
  202
+#define REMOTEIP3 0
  203
+#define REMOTEIP4 14
  204
+
  205
+static int tftp_get_v(unsigned int ip, const char *filename, char *buffer)
  206
+{
  207
+	int r;
  208
+
  209
+	r = tftp_get(ip, filename, buffer);
  210
+	if(r > 0)
  211
+		printf("Successfully downloaded %d bytes from %s over TFTP\n", r, filename);
  212
+	else
  213
+		printf("Unable to download %s over TFTP\n", filename);
  214
+	return r;
  215
+}
  216
+
  217
+void netboot(void)
  218
+{
  219
+	int size;
  220
+	unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
  221
+	unsigned int ip;
  222
+	unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;
  223
+
  224
+	printf("Booting from network...\n");
  225
+	printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
  226
+	printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
  227
+
  228
+	ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
  229
+
  230
+	microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
  231
+
  232
+	if(tftp_get_v(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) {
  233
+		printf("Network boot failed\n");
  234
+		return;
  235
+	}
  236
+
  237
+	cmdline_adr = SDRAM_BASE+0x1000000;
  238
+	size = tftp_get_v(ip, "cmdline.txt", (void *)cmdline_adr);
  239
+	if(size <= 0) {
  240
+		printf("No command line parameters found\n");
  241
+		cmdline_adr = 0;
  242
+	} else
  243
+		*((char *)(cmdline_adr+size)) = 0x00;
  244
+
  245
+	initrdstart_adr = SDRAM_BASE+0x1002000;
  246
+	size = tftp_get_v(ip, "initrd.bin", (void *)initrdstart_adr);
  247
+	if(size <= 0) {
  248
+		printf("No initial ramdisk found\n");
  249
+		initrdstart_adr = 0;
  250
+		initrdend_adr = 0;
  251
+	} else
  252
+		initrdend_adr = initrdstart_adr + size;
  253
+
  254
+	boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, SDRAM_BASE);
  255
+}
  256
+
  257
+void flashboot(void)
  258
+{
  259
+	unsigned int *flashbase;
  260
+	unsigned int length;
  261
+	unsigned int crc;
  262
+	unsigned int got_crc;
  263
+
  264
+	printf("Booting from flash...\n");
  265
+	if(rescue)
  266
+		flashbase = (unsigned int *)FLASH_OFFSET_RESCUE_APP;
  267
+	else
  268
+		flashbase = (unsigned int *)FLASH_OFFSET_REGULAR_APP;
  269
+	length = *flashbase++;
  270
+	crc = *flashbase++;
  271
+	if((length < 32) || (length > 4*1024*1024)) {
  272
+		printf("Error: Invalid flash boot image length\n");
  273
+		return;
  274
+	}
  275
+	
  276
+	printf("Loading %d bytes from flash...\n", length);
  277
+	memcpy((void *)SDRAM_BASE, flashbase, length);
  278
+	got_crc = crc32((unsigned char *)SDRAM_BASE, length);
  279
+	if(crc != got_crc) {
  280
+		printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc);
  281
+		return;
  282
+	}
  283
+	boot(0, 0, 0, rescue, SDRAM_BASE);
  284
+}
25  software/bios/boot.h
... ...
@@ -0,0 +1,25 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __BOOT_H
  19
+#define __BOOT_H
  20
+
  21
+void serialboot(void);
  22
+void netboot(void);
  23
+void flashboot(void);
  24
+
  25
+#endif /* __BOOT_H */
8  software/bios/ddrinit.c
@@ -33,10 +33,10 @@ static void cdelay(int i)
33 33
 
34 34
 static void setaddr(int a)
35 35
 {
36  
-	CSR_DFII_AH_P0 = (a & 0x1fe0) >> 5;
37  
-	CSR_DFII_AL_P0 = a & 0x001f;
38  
-	CSR_DFII_AH_P1 = (a & 0x1fe0) >> 5;
39  
-	CSR_DFII_AL_P1 = a & 0x001f;
  36
+	CSR_DFII_AH_P0 = (a & 0xff00) >> 8;
  37
+	CSR_DFII_AL_P0 = a & 0x00ff;
  38
+	CSR_DFII_AH_P1 = (a & 0xff00) >> 8;
  39
+	CSR_DFII_AL_P1 = a & 0x00ff;
40 40
 }
41 41
 
42 42
 static void init_sequence(void)
80  software/bios/main.c
@@ -26,8 +26,11 @@
26 26
 #include <extra/crc.h>
27 27
 
28 28
 #include <hw/flash.h>
  29
+#include <hw/minimac.h>
29 30
 
30 31
 #include "ddrinit.h"
  32
+#include "timer.h"
  33
+#include "boot.h"
31 34
 
32 35
 enum {
33 36
 	CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
@@ -311,9 +314,10 @@ static void help(void)
311 314
 	puts("crc        - compute CRC32 of a part of the address space");
312 315
 	puts("rcsr       - read processor CSR");
313 316
 	puts("wcsr       - write processor CSR");
  317
+	puts("netboot    - boot via TFTP");
  318
+	puts("serialboot - boot via SFL");
  319
+	puts("flashboot  - boot from flash");
314 320
 	puts("version    - display version");
315  
-	puts("reboot     - system reset");
316  
-	puts("reconf     - reload FPGA configuration");
317 321
 }
318 322
 
319 323
 static char *get_token(char **str)
@@ -343,6 +347,10 @@ static void do_command(char *c)
343 347
 	else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c));
344 348
 	else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c));
345 349
 
  350
+	else if(strcmp(token, "flashboot") == 0) flashboot();
  351
+	else if(strcmp(token, "serialboot") == 0) serialboot();
  352
+	else if(strcmp(token, "netboot") == 0) netboot();
  353
+	
346 354
 	else if(strcmp(token, "version") == 0) puts(VERSION);
347 355
 
348 356
 	else if(strcmp(token, "help") == 0) help();
@@ -390,6 +398,17 @@ static void crcbios(void)
390 398
 	}
391 399
 }
392 400
 
  401
+static void ethreset(void)
  402
+{
  403
+	CSR_MINIMAC_PHYRST = 0;
  404
+	busy_wait(2);
  405
+	/* that pesky ethernet PHY needs two resets at times... */
  406
+	CSR_MINIMAC_PHYRST = 1;
  407
+	busy_wait(2);
  408
+	CSR_MINIMAC_PHYRST = 0;
  409
+	busy_wait(2);
  410
+}
  411
+
393 412
 static void print_mac(void)
394 413
 {
395 414
 	unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;
@@ -437,6 +456,54 @@ static void readstr(char *s, int size)
437 456
 	}
438 457
 }
439 458
 
  459
+static int test_user_abort(void)
  460
+{
  461
+	char c;
  462
+
  463
+	printf("Automatic boot in 2 seconds...\n");
  464
+	printf("Q/ESC: abort boot\n");
  465
+	printf("F7:    boot from serial\n");
  466
+	printf("F8:    boot from network\n");
  467
+	timer_enable(0);
  468
+	timer_set_reload(0);
  469
+	timer_set_counter(get_system_frequency()*2);
  470
+	timer_enable(1);
  471
+	while(timer_get()) {
  472
+		if(readchar_nonblock()) {
  473
+			c = readchar();
  474
+			if((c == 'Q')||(c == '\e')) {
  475
+				puts("Aborted");
  476
+				return 0;
  477
+			}
  478
+			if(c == 0x06) {
  479
+				serialboot();
  480
+				return 0;
  481
+			}
  482
+			if(c == 0x07) {
  483
+				netboot();
  484
+				return 0;
  485
+			}
  486
+		}
  487
+	}
  488
+	return 1;
  489
+}
  490
+
  491
+static void boot_sequence(void)
  492
+{
  493
+	if(test_user_abort()) {
  494
+		if(rescue) {
  495
+			netboot();
  496
+			serialboot();
  497
+			flashboot();
  498
+		} else {
  499
+			flashboot();
  500
+			netboot();
  501
+			serialboot();
  502
+		}
  503
+		printf("No boot medium found\n");
  504
+	}
  505
+}
  506
+
440 507
 int main(int i, char **c)
441 508
 {
442 509
 	char buffer[64];
@@ -452,14 +519,13 @@ int main(int i, char **c)
452 519
 	if(rescue)
453 520
 		printf("Rescue mode\n");
454 521
 	board_init();
  522
+	ethreset();
455 523
 	print_mac();
456 524
 	ddr_ok = ddrinit();
457  
-	if(ddr_ok) {
458  
-		printf("Booting...\n");
459  
-	} else {
  525
+	if(ddr_ok)
  526
+		boot_sequence();
  527
+	else
460 528
 		printf("Memory initialization failed\n");
461  
-	}
462  
-	
463 529
 	
464 530
 	while(1) {
465 531
 		putsnonl("\e[1mBIOS>\e[0m ");
400  software/bios/microudp.c
... ...
@@ -0,0 +1,400 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <stdio.h>
  19
+#include <system.h>
  20
+#include <extra/crc.h>
  21
+#include <hw/minimac.h>
  22
+
  23
+#include "microudp.h"
  24
+
  25
+#define ETHERTYPE_ARP 0x0806
  26
+#define ETHERTYPE_IP  0x0800
  27
+
  28
+struct ethernet_header {
  29
+	unsigned char preamble[8];
  30
+	unsigned char destmac[6];
  31
+	unsigned char srcmac[6];
  32
+	unsigned short ethertype;
  33
+} __attribute__((packed));
  34
+
  35
+static void fill_eth_header(struct ethernet_header *h, const unsigned char *destmac, const unsigned char *srcmac, unsigned short ethertype)
  36
+{
  37
+	int i;
  38
+
  39
+	for(i=0;i<7;i++)
  40
+		h->preamble[i] = 0x55;
  41
+	h->preamble[7] = 0xd5;
  42
+	for(i=0;i<6;i++)
  43
+		h->destmac[i] = destmac[i];
  44
+	for(i=0;i<6;i++)
  45
+		h->srcmac[i] = srcmac[i];
  46
+	h->ethertype = ethertype;
  47
+}
  48
+
  49
+#define ARP_HWTYPE_ETHERNET 0x0001
  50
+#define ARP_PROTO_IP        0x0800
  51
+
  52
+#define ARP_OPCODE_REQUEST  0x0001
  53
+#define ARP_OPCODE_REPLY    0x0002
  54
+
  55
+struct arp_frame {
  56
+	unsigned short hwtype;
  57
+	unsigned short proto;
  58
+	unsigned char hwsize;
  59
+	unsigned char protosize;
  60
+	unsigned short opcode;
  61
+	unsigned char sender_mac[6];
  62
+	unsigned int sender_ip;
  63
+	unsigned char target_mac[6];
  64
+	unsigned int target_ip;
  65
+	unsigned char padding[18];
  66
+} __attribute__((packed));
  67
+
  68
+#define IP_IPV4			0x45
  69
+#define IP_DONT_FRAGMENT	0x4000
  70
+#define IP_TTL			64
  71
+#define IP_PROTO_UDP		0x11
  72
+
  73
+struct ip_header {
  74
+	unsigned char version;
  75
+	unsigned char diff_services;
  76
+	unsigned short total_length;
  77
+	unsigned short identification;
  78
+	unsigned short fragment_offset;
  79
+	unsigned char ttl;
  80
+	unsigned char proto;
  81
+	unsigned short checksum;
  82
+	unsigned int src_ip;
  83
+	unsigned int dst_ip;
  84
+} __attribute__((packed));
  85
+
  86
+struct udp_header {
  87
+	unsigned short src_port;
  88
+	unsigned short dst_port;
  89
+	unsigned short length;
  90
+	unsigned short checksum;
  91
+} __attribute__((packed));
  92
+
  93
+struct udp_frame {
  94
+	struct ip_header ip;
  95
+	struct udp_header udp;
  96
+	char payload[];
  97
+} __attribute__((packed));
  98
+
  99
+struct ethernet_frame {
  100
+	struct ethernet_header eth_header;
  101
+	union {
  102
+		struct arp_frame arp;
  103
+		struct udp_frame udp;
  104
+	} contents;
  105
+} __attribute__((packed));
  106
+
  107
+typedef union {
  108
+	struct ethernet_frame frame;
  109
+	unsigned char raw[1532];
  110
+} ethernet_buffer;
  111
+
  112
+
  113
+static int rxlen;
  114
+static ethernet_buffer *rxbuffer;
  115
+static ethernet_buffer *rxbuffer0;
  116
+static ethernet_buffer *rxbuffer1;
  117
+static int txlen;
  118
+static ethernet_buffer *txbuffer;
  119
+
  120
+static void send_packet(void)
  121
+{
  122
+	unsigned int crc;
  123
+	
  124
+	crc = crc32(&txbuffer->raw[8], txlen-8);
  125
+	txbuffer->raw[txlen  ] = (crc & 0xff);
  126
+	txbuffer->raw[txlen+1] = (crc & 0xff00) >> 8;
  127
+	txbuffer->raw[txlen+2] = (crc & 0xff0000) >> 16;
  128
+	txbuffer->raw[txlen+3] = (crc & 0xff000000) >> 24;
  129
+	txlen += 4;
  130
+	CSR_MINIMAC_TXCOUNTH = (txlen & 0xff00) >> 8;
  131
+	CSR_MINIMAC_TXCOUNTL = txlen & 0x00ff;
  132
+	CSR_MINIMAC_TXSTART = 1;
  133
+	while(!(CSR_MINIMAC_EV_PENDING & MINIMAC_EV_TX));
  134
+	CSR_MINIMAC_EV_PENDING = MINIMAC_EV_TX;
  135
+}
  136
+
  137
+static unsigned char my_mac[6];
  138
+static unsigned int my_ip;
  139
+
  140
+/* ARP cache - one entry only */
  141
+static unsigned char cached_mac[6];
  142
+static unsigned int cached_ip;
  143
+
  144
+static void process_arp(void)
  145
+{
  146
+	if(rxlen < 68) return;
  147
+	if(rxbuffer->frame.contents.arp.hwtype != ARP_HWTYPE_ETHERNET) return;
  148
+	if(rxbuffer->frame.contents.arp.proto != ARP_PROTO_IP) return;
  149
+	if(rxbuffer->frame.contents.arp.hwsize != 6) return;
  150
+	if(rxbuffer->frame.contents.arp.protosize != 4) return;
  151
+	if(rxbuffer->frame.contents.arp.opcode == ARP_OPCODE_REPLY) {
  152
+		if(rxbuffer->frame.contents.arp.sender_ip == cached_ip) {
  153
+			int i;
  154
+			for(i=0;i<6;i++)
  155
+				cached_mac[i] = rxbuffer->frame.contents.arp.sender_mac[i];
  156
+		}
  157
+		return;
  158
+	}
  159
+	if(rxbuffer->frame.contents.arp.opcode == ARP_OPCODE_REQUEST) {
  160
+		if(rxbuffer->frame.contents.arp.target_ip == my_ip) {
  161
+			int i;
  162
+			
  163
+			fill_eth_header(&txbuffer->frame.eth_header,
  164
+				rxbuffer->frame.contents.arp.sender_mac,
  165
+				my_mac,
  166
+				ETHERTYPE_ARP);
  167
+			txlen = 68;
  168
+			txbuffer->frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
  169
+			txbuffer->frame.contents.arp.proto = ARP_PROTO_IP;
  170
+			txbuffer->frame.contents.arp.hwsize = 6;
  171
+			txbuffer->frame.contents.arp.protosize = 4;
  172
+			txbuffer->frame.contents.arp.opcode = ARP_OPCODE_REPLY;
  173
+			txbuffer->frame.contents.arp.sender_ip = my_ip;
  174
+			for(i=0;i<6;i++)
  175
+				txbuffer->frame.contents.arp.sender_mac[i] = my_mac[i];
  176
+			txbuffer->frame.contents.arp.target_ip = rxbuffer->frame.contents.arp.sender_ip;
  177
+			for(i=0;i<6;i++)
  178
+				txbuffer->frame.contents.arp.target_mac[i] = rxbuffer->frame.contents.arp.sender_mac[i];
  179
+			send_packet();
  180
+		}
  181
+		return;
  182
+	}
  183
+}
  184
+
  185
+static const unsigned char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  186
+
  187
+int microudp_arp_resolve(unsigned int ip)
  188
+{
  189
+	int i;
  190
+	int tries;
  191
+	int timeout;
  192
+
  193
+	if(cached_ip == ip) {
  194
+		for(i=0;i<6;i++)
  195
+			if(cached_mac[i]) return 1;
  196
+	}
  197
+	cached_ip = ip;
  198
+	for(i=0;i<6;i++)
  199
+		cached_mac[i] = 0;
  200
+
  201
+	for(tries=0;tries<5;tries++) {
  202
+		/* Send an ARP request */
  203
+		fill_eth_header(&txbuffer->frame.eth_header,
  204
+				broadcast,
  205
+				my_mac,
  206
+				ETHERTYPE_ARP);
  207
+		txlen = 68;
  208
+		txbuffer->frame.contents.arp.hwtype = ARP_HWTYPE_ETHERNET;
  209
+		txbuffer->frame.contents.arp.proto = ARP_PROTO_IP;
  210
+		txbuffer->frame.contents.arp.hwsize = 6;
  211
+		txbuffer->frame.contents.arp.protosize = 4;
  212
+		txbuffer->frame.contents.arp.opcode = ARP_OPCODE_REQUEST;
  213
+		txbuffer->frame.contents.arp.sender_ip = my_ip;
  214
+		for(i=0;i<6;i++)
  215
+			txbuffer->frame.contents.arp.sender_mac[i] = my_mac[i];
  216
+		txbuffer->frame.contents.arp.target_ip = ip;
  217
+		for(i=0;i<6;i++)
  218
+			txbuffer->frame.contents.arp.target_mac[i] = 0;
  219
+		send_packet();
  220
+
  221
+		/* Do we get a reply ? */
  222
+		for(timeout=0;timeout<2000000;timeout++) {
  223
+			microudp_service();
  224
+			for(i=0;i<6;i++)
  225
+				if(cached_mac[i]) return 1;
  226
+		}
  227
+	}
  228
+
  229
+	return 0;
  230
+}
  231
+
  232
+static unsigned short ip_checksum(unsigned int r, void *buffer, unsigned int length, int complete)
  233
+{
  234
+	unsigned char *ptr;
  235
+	int i;
  236
+
  237
+	ptr = (unsigned char *)buffer;
  238
+	length >>= 1;
  239
+
  240
+	for(i=0;i<length;i++)
  241
+		r += ((unsigned int)(ptr[2*i]) << 8)|(unsigned int)(ptr[2*i+1]) ;
  242
+
  243
+	/* Add overflows */
  244
+	while(r >> 16)
  245
+		r = (r & 0xffff) + (r >> 16);
  246
+
  247
+	if(complete) {
  248
+		r = ~r;
  249
+		r &= 0xffff;
  250
+		if(r == 0) r = 0xffff;
  251
+	}
  252
+	return r;
  253
+}
  254
+
  255
+void *microudp_get_tx_buffer(void)
  256
+{
  257
+	return txbuffer->frame.contents.udp.payload;
  258
+}
  259
+
  260
+struct pseudo_header {
  261
+	unsigned int src_ip;
  262
+	unsigned int dst_ip;
  263
+	unsigned char zero;
  264
+	unsigned char proto;
  265
+	unsigned short length;
  266
+} __attribute__((packed));
  267
+
  268
+int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int length)
  269
+{
  270
+	struct pseudo_header h;
  271
+	unsigned int r;
  272
+	
  273
+	if((cached_mac[0] == 0) && (cached_mac[1] == 0) && (cached_mac[2] == 0)
  274
+		&& (cached_mac[3] == 0) && (cached_mac[4] == 0) && (cached_mac[5] == 0))
  275
+		return 0;
  276
+
  277
+	txlen = length + sizeof(struct ethernet_header) + sizeof(struct udp_frame) + 8;
  278
+	if(txlen < 72) txlen = 72;
  279
+	
  280
+	fill_eth_header(&txbuffer->frame.eth_header,
  281
+		cached_mac,
  282
+		my_mac,
  283
+		ETHERTYPE_IP);
  284
+	
  285
+	txbuffer->frame.contents.udp.ip.version = IP_IPV4;
  286
+	txbuffer->frame.contents.udp.ip.diff_services = 0;
  287
+	txbuffer->frame.contents.udp.ip.total_length = length + sizeof(struct udp_frame);
  288
+	txbuffer->frame.contents.udp.ip.identification = 0;
  289
+	txbuffer->frame.contents.udp.ip.fragment_offset = IP_DONT_FRAGMENT;
  290
+	txbuffer->frame.contents.udp.ip.ttl = IP_TTL;
  291
+	h.proto = txbuffer->frame.contents.udp.ip.proto = IP_PROTO_UDP;
  292
+	txbuffer->frame.contents.udp.ip.checksum = 0;
  293
+	h.src_ip = txbuffer->frame.contents.udp.ip.src_ip = my_ip;
  294
+	h.dst_ip = txbuffer->frame.contents.udp.ip.dst_ip = cached_ip;
  295
+	txbuffer->frame.contents.udp.ip.checksum = ip_checksum(0, &txbuffer->frame.contents.udp.ip,
  296
+		sizeof(struct ip_header), 1);
  297
+
  298
+	txbuffer->frame.contents.udp.udp.src_port = src_port;
  299
+	txbuffer->frame.contents.udp.udp.dst_port = dst_port;
  300
+	h.length = txbuffer->frame.contents.udp.udp.length = length + sizeof(struct udp_header);
  301
+	txbuffer->frame.contents.udp.udp.checksum = 0;
  302
+
  303
+	h.zero = 0;
  304
+	r = ip_checksum(0, &h, sizeof(struct pseudo_header), 0);
  305
+	if(length & 1) {
  306
+		txbuffer->frame.contents.udp.payload[length] = 0;
  307
+		length++;
  308
+	}
  309
+	r = ip_checksum(r, &txbuffer->frame.contents.udp.udp,
  310
+		sizeof(struct udp_header)+length, 1);
  311
+	txbuffer->frame.contents.udp.udp.checksum = r;
  312
+	
  313
+	send_packet();
  314
+
  315
+	return 1;
  316
+}
  317
+
  318
+static udp_callback rx_callback;
  319
+
  320
+static void process_ip(void)
  321
+{
  322
+	if(rxlen < (sizeof(struct ethernet_header)+sizeof(struct udp_frame))) return;
  323
+	/* We don't verify UDP and IP checksums and rely on the Ethernet checksum solely */
  324
+	if(rxbuffer->frame.contents.udp.ip.version != IP_IPV4) return;
  325
+	// check disabled for QEMU compatibility
  326
+	//if(rxbuffer->frame.contents.udp.ip.diff_services != 0) return;
  327
+	if(rxbuffer->frame.contents.udp.ip.total_length < sizeof(struct udp_frame)) return;
  328
+	// check disabled for QEMU compatibility
  329
+	//if(rxbuffer->frame.contents.udp.ip.fragment_offset != IP_DONT_FRAGMENT) return;
  330
+	if(rxbuffer->frame.contents.udp.ip.proto != IP_PROTO_UDP) return;
  331
+	if(rxbuffer->frame.contents.udp.ip.dst_ip != my_ip) return;
  332
+	if(rxbuffer->frame.contents.udp.udp.length < sizeof(struct udp_header)) return;
  333
+
  334
+	if(rx_callback)
  335
+		rx_callback(rxbuffer->frame.contents.udp.ip.src_ip, rxbuffer->frame.contents.udp.udp.src_port, rxbuffer->frame.contents.udp.udp.dst_port, rxbuffer->frame.contents.udp.payload, rxbuffer->frame.contents.udp.udp.length-sizeof(struct udp_header));
  336
+}
  337
+
  338
+void microudp_set_callback(udp_callback callback)
  339
+{
  340
+	rx_callback = callback;
  341
+}
  342
+
  343
+static void process_frame(void)
  344
+{
  345
+	int i;
  346
+	unsigned int received_crc;
  347
+	unsigned int computed_crc;
  348
+
  349
+	flush_cpu_dcache();
  350
+	for(i=0;i<7;i++)
  351
+		if(rxbuffer->frame.eth_header.preamble[i] != 0x55) return;
  352
+	if(rxbuffer->frame.eth_header.preamble[7] != 0xd5) return;
  353
+	received_crc = ((unsigned int)rxbuffer->raw[rxlen-1] << 24)
  354
+		|((unsigned int)rxbuffer->raw[rxlen-2] << 16)
  355
+		|((unsigned int)rxbuffer->raw[rxlen-3] <<  8)
  356
+		|((unsigned int)rxbuffer->raw[rxlen-4]);
  357
+	computed_crc = crc32(&rxbuffer->raw[8], rxlen-12);
  358
+	if(received_crc != computed_crc) return;
  359
+
  360
+	rxlen -= 4; /* strip CRC here to be consistent with TX */
  361
+	if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_ARP) process_arp();
  362
+	else if(rxbuffer->frame.eth_header.ethertype == ETHERTYPE_IP) process_ip();
  363
+}
  364
+
  365
+void microudp_start(unsigned char *macaddr, unsigned int ip)
  366
+{
  367
+	int i;
  368
+
  369
+	CSR_MINIMAC_EV_PENDING = MINIMAC_EV_RX0 | MINIMAC_EV_RX1 | MINIMAC_EV_TX;
  370
+	
  371
+	rxbuffer0 = (ethernet_buffer *)MINIMAC_RX0_BASE;
  372
+	rxbuffer1 = (ethernet_buffer *)MINIMAC_RX1_BASE;
  373
+	txbuffer = (ethernet_buffer *)MINIMAC_TX_BASE;
  374
+
  375
+	for(i=0;i<6;i++)
  376
+		my_mac[i] = macaddr[i];
  377
+	my_ip = ip;
  378
+
  379
+	cached_ip = 0;
  380
+	for(i=0;i<6;i++)
  381
+		cached_mac[i] = 0;
  382
+
  383
+	rx_callback = (udp_callback)0;
  384
+}
  385
+
  386
+void microudp_service(void)
  387
+{
  388
+	if(CSR_MINIMAC_EV_PENDING & MINIMAC_EV_RX0) {
  389
+		rxlen = (CSR_MINIMAC_RXCOUNT0H << 8) | CSR_MINIMAC_RXCOUNT0L;
  390
+		rxbuffer = rxbuffer0;
  391
+		process_frame();
  392
+		CSR_MINIMAC_EV_PENDING = MINIMAC_EV_RX0;
  393
+	}
  394
+	if(CSR_MINIMAC_EV_PENDING & MINIMAC_EV_RX1) {
  395
+		rxlen = (CSR_MINIMAC_RXCOUNT1H << 8) | CSR_MINIMAC_RXCOUNT1L;
  396
+		rxbuffer = rxbuffer1;
  397
+		process_frame();
  398
+		CSR_MINIMAC_EV_PENDING = MINIMAC_EV_RX1;
  399
+	}
  400
+}
34  software/bios/microudp.h
... ...
@@ -0,0 +1,34 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __NET_MICROUDP_H
  19
+#define __NET_MICROUDP_H
  20
+
  21
+#define IPTOINT(a, b, c, d) ((a << 24)|(b << 16)|(c << 8)|d)
  22
+
  23
+#define MICROUDP_BUFSIZE (5*1532)
  24
+
  25
+typedef void (*udp_callback)(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *data, unsigned int length);
  26
+
  27
+void microudp_start(unsigned char *macaddr, unsigned int ip);
  28
+int microudp_arp_resolve(unsigned int ip);
  29
+void *microudp_get_tx_buffer(void);
  30
+int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int length);
  31
+void microudp_set_callback(udp_callback callback);
  32
+void microudp_service(void);
  33
+
  34
+#endif /* __NET_MICROUDP_H */
136  software/bios/tftp.c
... ...
@@ -0,0 +1,136 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <string.h>
  19
+
  20
+#include "microudp.h"
  21
+#include "tftp.h"
  22
+
  23
+#define PORT_OUT	69
  24
+#define PORT_IN		7642
  25
+
  26
+static int format_request(char *buf, const char *filename)
  27
+{
  28
+	*buf++ = 0x00; /* Opcode: Request */
  29
+	*buf++ = 0x01;
  30
+	strcpy(buf, filename);
  31
+	buf += strlen(filename);
  32
+	*buf++ = 0x00;
  33
+	*buf++ = 'o';
  34
+	*buf++ = 'c';
  35
+	*buf++ = 't';
  36
+	*buf++ = 'e';
  37
+	*buf++ = 't';
  38
+	*buf++ = 0x00;
  39
+	return 9+strlen(filename);
  40
+}
  41
+
  42
+static int format_ack(char *buf, unsigned short block)
  43
+{
  44
+	*buf++ = 0x00; /* Opcode: Ack */
  45
+	*buf++ = 0x04;
  46
+	*buf++ = (block & 0xff00) >> 8;
  47
+	*buf++ = (block & 0x00ff);
  48
+	return 4;
  49
+}
  50
+
  51
+static char *packet_data;
  52
+static int total_length;
  53
+static int transfer_finished;
  54
+static char *dst_buffer;
  55
+
  56
+static void rx_callback(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *_data, unsigned int length)
  57
+{
  58
+	unsigned char *data = (unsigned char *)_data;
  59
+	unsigned short opcode;
  60
+	unsigned short block;
  61
+	int i;
  62
+	int offset;
  63
+	
  64
+	if(length < 4) return;
  65
+	if(dst_port != PORT_IN) return;
  66
+	opcode = ((unsigned short)(data[0]) << 8)|((unsigned short)(data[1]));
  67
+	block = ((unsigned short)(data[2]) << 8)|((unsigned short)(data[3]));
  68
+	if(block < 1) return;
  69
+	if(opcode == 3) { /* Data */
  70
+		length -= 4;
  71
+		offset = (block-1)*512;
  72
+		for(i=0;i<length;i++)
  73
+			dst_buffer[offset+i] = data[i+4];
  74
+		total_length += length;
  75
+		if(length < 512)
  76
+			transfer_finished = 1;
  77
+		
  78
+		length = format_ack(packet_data, block);
  79
+		microudp_send(PORT_IN, src_port, length);
  80
+	}
  81
+	if(opcode == 5) { /* Error */
  82
+		total_length = -1;
  83
+		transfer_finished = 1;
  84
+	}
  85
+}
  86
+
  87
+int tftp_get(unsigned int ip, const char *filename, char *buffer)
  88
+{
  89
+	int len;
  90
+	int tries;
  91
+	int i;
  92
+	int length_before;
  93
+	
  94
+	if(!microudp_arp_resolve(ip))
  95
+		return -1;
  96
+
  97
+	microudp_set_callback(rx_callback);
  98
+
  99
+	packet_data = microudp_get_tx_buffer();
  100
+	dst_buffer = buffer;
  101
+
  102
+	total_length = 0;
  103
+	transfer_finished = 0;
  104
+	tries = 5;
  105
+	while(1) {
  106
+		len = format_request(packet_data, filename);
  107
+		microudp_send(PORT_IN, PORT_OUT, len);
  108
+		for(i=0;i<2000000;i++) {
  109
+			microudp_service();
  110
+			if((total_length > 0) || transfer_finished) break;
  111
+		}
  112
+		if((total_length > 0) || transfer_finished) break;
  113
+		tries--;
  114
+		if(tries == 0) {
  115
+			microudp_set_callback(NULL);
  116
+			return -1;
  117
+		}
  118
+	}
  119
+
  120
+	length_before = total_length;
  121
+	while(!transfer_finished) {
  122
+		if(length_before != total_length) {
  123
+			i = 12000000;
  124
+			length_before = total_length;
  125
+		}
  126
+		if(i-- == 0) {
  127
+			microudp_set_callback(NULL);
  128
+			return -1;
  129
+		}
  130
+		microudp_service();
  131
+	}
  132
+
  133
+	microudp_set_callback(NULL);
  134
+
  135
+	return total_length;
  136
+}
24  software/bios/tftp.h
... ...
@@ -0,0 +1,24 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __NET_TFTP_H
  19
+#define __NET_TFTP_H
  20
+
  21
+int tftp_get(unsigned int ip, const char *filename, char *buffer);
  22
+
  23
+#endif /* __NET_TFTP_H */
  24
+
63  software/bios/timer.c
... ...
@@ -0,0 +1,63 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#include <hw/timer.h>
  19
+
  20
+#include "timer.h"
  21
+
  22
+unsigned int get_system_frequency(void)
  23
+{
  24
+	return 83333333; /* TODO */
  25
+}
  26
+
  27
+void timer_enable(int en)
  28
+{
  29
+	CSR_TIMER0_EN = en;
  30
+}
  31
+
  32
+unsigned int timer_get(void)
  33
+{
  34
+	return (CSR_TIMER0_COUNT3 << 24)
  35
+		|(CSR_TIMER0_COUNT2 << 16)
  36
+		|(CSR_TIMER0_COUNT1 << 8)
  37
+		|CSR_TIMER0_COUNT0;
  38
+}
  39
+
  40
+void timer_set_counter(unsigned int value)
  41
+{
  42
+	CSR_TIMER0_COUNT3 = (value & 0xff000000) >> 24;
  43
+	CSR_TIMER0_COUNT2 = (value & 0x00ff0000) >> 16;
  44
+	CSR_TIMER0_COUNT1 = (value & 0x0000ff00) >> 8;
  45
+	CSR_TIMER0_COUNT0 = value & 0x000000ff;
  46
+}
  47
+
  48
+void timer_set_reload(unsigned int value)
  49
+{
  50
+	CSR_TIMER0_RELOAD3 = (value & 0xff000000) >> 24;
  51
+	CSR_TIMER0_RELOAD2 = (value & 0x00ff0000) >> 16;
  52
+	CSR_TIMER0_RELOAD1 = (value & 0x0000ff00) >> 8;
  53
+	CSR_TIMER0_RELOAD0 = value & 0x000000ff;
  54
+}
  55
+
  56
+void busy_wait(unsigned int ds)
  57
+{
  58
+	timer_enable(0);
  59
+	timer_set_reload(0);
  60
+	timer_set_counter(get_system_frequency()/10*ds);
  61
+	timer_enable(1);
  62
+	while(timer_get());
  63
+}
28  software/bios/timer.h
... ...
@@ -0,0 +1,28 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __TIMER_H
  19
+#define __TIMER_H
  20
+
  21
+unsigned int get_system_frequency(void);
  22
+void timer_enable(int en);
  23
+unsigned int timer_get(void);
  24
+void timer_set_counter(unsigned int value);
  25
+void timer_set_reload(unsigned int value);
  26
+void busy_wait(unsigned int ms);
  27
+
  28
+#endif /* __TIMER_H */
49  software/include/hw/minimac.h
... ...
@@ -0,0 +1,49 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __HW_MINIMAC_H
  19
+#define __HW_MINIMAC_H
  20
+
  21
+#include <hw/common.h>
  22
+#include <csrbase.h>
  23
+
  24
+#define MINIMAC_CSR(x)		MMPTR(MINIMAC_BASE+(x))
  25
+
  26
+#define CSR_MINIMAC_PHYRST	MINIMAC_CSR(0x00)
  27
+
  28
+#define CSR_MINIMAC_RXCOUNT0H	MINIMAC_CSR(0x04)
  29
+#define CSR_MINIMAC_RXCOUNT0L	MINIMAC_CSR(0x08)
  30
+#define CSR_MINIMAC_RXCOUNT1H	MINIMAC_CSR(0x0C)
  31
+#define CSR_MINIMAC_RXCOUNT1L	MINIMAC_CSR(0x10)
  32
+
  33
+#define CSR_MINIMAC_TXCOUNTH	MINIMAC_CSR(0x14)
  34
+#define CSR_MINIMAC_TXCOUNTL	MINIMAC_CSR(0x18)
  35
+#define CSR_MINIMAC_TXSTART	MINIMAC_CSR(0x1C)
  36
+
  37
+#define CSR_MINIMAC_EV_STAT	MINIMAC_CSR(0x20)
  38
+#define CSR_MINIMAC_EV_PENDING	MINIMAC_CSR(0x24)
  39
+#define CSR_MINIMAC_EV_ENABLE	MINIMAC_CSR(0x28)
  40
+
  41
+#define MINIMAC_EV_RX0		0x1
  42
+#define MINIMAC_EV_RX1		0x2
  43
+#define MINIMAC_EV_TX		0x4
  44
+
  45
+#define MINIMAC_RX0_BASE	0xb0000000
  46
+#define MINIMAC_RX1_BASE	0xb0000800
  47
+#define MINIMAC_TX_BASE		0xb0001000
  48
+
  49
+#endif /* __HW_MINIMAC_H */
44  software/include/hw/timer.h
... ...
@@ -0,0 +1,44 @@
  1
+/*
  2
+ * Milkymist SoC (Software)
  3
+ * Copyright (C) 2007, 2008, 2009, 2010, 2012 Sebastien Bourdeauducq
  4
+ *
  5
+ * This program is free software: you can redistribute it and/or modify
  6
+ * it under the terms of the GNU General Public License as published by
  7
+ * the Free Software Foundation, version 3 of the License.
  8
+ *
  9
+ * This program is distributed in the hope that it will be useful,
  10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12
+ * GNU General Public License for more details.
  13
+ *
  14
+ * You should have received a copy of the GNU General Public License
  15
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16
+ */
  17
+
  18
+#ifndef __HW_TIMER_H
  19
+#define __HW_TIMER_H
  20
+
  21
+#include <hw/common.h>
  22
+#include <csrbase.h>
  23
+
  24
+#define TIMER0_CSR(x)		MMPTR(TIMER0_BASE+(x))
  25
+
  26
+#define CSR_TIMER0_EN		TIMER0_CSR(0x00)
  27
+
  28
+#define CSR_TIMER0_COUNT3	TIMER0_CSR(0x04)
  29
+#define CSR_TIMER0_COUNT2	TIMER0_CSR(0x08)
  30
+#define CSR_TIMER0_COUNT1	TIMER0_CSR(0x0C)
  31
+#define CSR_TIMER0_COUNT0	TIMER0_CSR(0x10)
  32
+
  33
+#define CSR_TIMER0_RELOAD3	TIMER0_CSR(0x14)
  34
+#define CSR_TIMER0_RELOAD2	TIMER0_CSR(0x18)
  35
+#define CSR_TIMER0_RELOAD1	TIMER0_CSR(0x1C)
  36
+#define CSR_TIMER0_RELOAD0	TIMER0_CSR(0x20)
  37
+
  38
+#define CSR_TIMER0_EV_STAT	TIMER0_CSR(0x24)
  39
+#define CSR_TIMER0_EV_PENDING	TIMER0_CSR(0x28)
  40
+#define CSR_TIMER0_EV_ENABLE	TIMER0_CSR(0x2C)
  41
+
  42
+#define TIMER0_EV		0x1
  43
+
  44
+#endif /* __HW_TIMER_H */
8  tools/mkmmimg.c
... ...
@@ -1,6 +1,6 @@
1 1
 /*
2 2
  * CRC32 computation tool and Milkymist image file writer
3  
- * (c) 2009, 2010, Sebastien Bourdeauducq
  3
+ * (c) 2009, 2010, 2012 Sebastien Bourdeauducq
4 4
  * Released under GNU GPL v3
5 5
  * This file is part of Milkymist.
6 6
  */
@@ -102,8 +102,8 @@ int main(int argc, char *argv[])
102 102
 	unsigned int crc;
103 103
 	
104 104
 	if(((argc != 2) && (argc != 3) && (argc != 4))
105  
-		|| ((argc > 2) && (strcmp(argv[2], "write") && (strcmp(argv[2], "writelzma"))))) {
106  
-		fprintf(stderr, "Usage: mkmmimg <filename> [write[lzma]] [dest]\n");
  105
+		|| ((argc > 2) && (strcmp(argv[2], "write")))) {
  106
+		fprintf(stderr, "Usage: mkmmimg <filename> [write] [dest]\n");
107 107
 		return 1;
108 108
 	}
109 109
 	
@@ -155,8 +155,6 @@ int main(int argc, char *argv[])
155 155
 		b[1] = (length & 0x00ff0000) >> 16;
156 156
 		b[2] = (length & 0x0000ff00) >> 8;
157 157
 		b[3] = (length & 0x000000ff) >> 0;
158  
-		if(strcmp(argv[2], "writelzma") == 0)
159  
-			b[0] |= 0x80;
160 158
 		write(fd_out, &b[0], 4);
161 159
 		b[0] = (crc & 0xff000000) >> 24;
162 160
 		b[1] = (crc & 0x00ff0000) >> 16;

No commit comments for this range

Something went wrong with that request. Please try again.