add initial support for the crisarchitecture used on foxboards to openwrt
[openwrt.git] / target / linux / etrax-2.6 / image / e100boot / src / cbl / src / net_init.c
1 #define net_init            init_interface
2 #define handle_network_read handle_read
3 #define send_network_ack    send_ack
4 #define send_network_string send_string
5 #define send_network_hex    send_hex
6
7 #include "sv_addr_ag.h"
8 #include "e100boot.h"
9
10 static void start_network_trans(void);
11
12 void 
13 net_init(void)
14 {
15   *R_NETWORK_GA_1 = *R_NETWORK_GA_0 = 0;
16   
17   SET_ETHER_ADDR(0x01,0x40,0x8c,0x00,0x01,0x00,
18                  0x01,0x40,0x8c,0x00,0x01,0x00);
19
20   *R_NETWORK_REC_CONFIG =  
21     IO_STATE (R_NETWORK_REC_CONFIG, duplex,     half)    |
22     IO_STATE (R_NETWORK_REC_CONFIG, bad_crc,    discard) |
23     IO_STATE (R_NETWORK_REC_CONFIG, oversize,   discard) |
24     IO_STATE (R_NETWORK_REC_CONFIG, undersize,  discard) |
25     IO_STATE (R_NETWORK_REC_CONFIG, all_roots,  discard) |
26     IO_STATE (R_NETWORK_REC_CONFIG, broadcast,  discard) |
27     IO_STATE (R_NETWORK_REC_CONFIG, individual, discard) |
28     IO_STATE (R_NETWORK_REC_CONFIG, ma1,        disable) |
29     IO_STATE (R_NETWORK_REC_CONFIG, ma0,        enable);
30
31   *R_NETWORK_MGM_CTRL =  
32     IO_FIELD(R_NETWORK_MGM_CTRL, txd_pins, 0)       |
33     IO_FIELD(R_NETWORK_MGM_CTRL, txer_pin, 0)       |
34     IO_FIELD(R_NETWORK_MGM_CTRL, mdck,     0)       |
35     IO_STATE(R_NETWORK_MGM_CTRL, mdoe,     disable) |
36     IO_FIELD(R_NETWORK_MGM_CTRL, mdio,     0);
37   
38   *R_NETWORK_TR_CTRL = 
39     (IO_STATE (R_NETWORK_TR_CTRL, clr_error, clr)     |
40      IO_STATE (R_NETWORK_TR_CTRL, delay,     none)    |
41      IO_STATE (R_NETWORK_TR_CTRL, cancel,    dont)    |
42      IO_STATE (R_NETWORK_TR_CTRL, cd,        enable)  |
43      IO_STATE (R_NETWORK_TR_CTRL, pad,       enable) |
44      IO_STATE (R_NETWORK_TR_CTRL, crc,       enable)  |
45      IO_STATE (R_NETWORK_TR_CTRL, retry,     enable));
46      
47   *R_NETWORK_GEN_CONFIG =  
48     IO_STATE (R_NETWORK_GEN_CONFIG, loopback, off)   |
49     IO_STATE (R_NETWORK_GEN_CONFIG, frame,    ether) |
50     IO_STATE (R_NETWORK_GEN_CONFIG, vg,       off)   |
51     IO_STATE (R_NETWORK_GEN_CONFIG, phy,      mii_clk)   |
52     IO_STATE (R_NETWORK_GEN_CONFIG, enable,   on);
53
54   *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset);
55   *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset);
56
57   rx_descr.sw_len = NETWORK_HEADER_LENGTH;
58   rx_descr.ctrl   = TX_CTRL;
59   rx_descr.next   = (udword)&rx_descr2;
60   rx_descr.buf    = (udword)&rx_header;
61
62   rx_descr2.sw_len = 1500;
63   rx_descr2.ctrl   = TX_CTRL_EOP;
64   rx_descr2.buf    = target_address;
65
66   /* Endian dependent, but saves a few bytes... */
67   *(udword*)&tx_header.src[0] = htonl(0x02408c00); 
68   *(uword*)&tx_header.src[4]  = htons(0x0100); 
69   tx_header.length = htons(64);
70   tx_header.snap1  = htonl(0xaaaa0300);
71   tx_header.snap2  = htonl(0x408c8856);
72   tx_header.tag    = htonl(0xfffffffe);
73   tx_header.seq    = 0;
74   tx_header.type   = 0;
75
76   tx_descr.sw_len = NETWORK_HEADER_LENGTH;
77   tx_descr.ctrl   = TX_CTRL_EOP;
78   tx_descr.buf    = (udword)&tx_header;
79   
80   set_dest        = FALSE;
81   seq = 0;
82
83   *R_DMA_CH1_FIRST = (udword)&rx_descr;
84   *R_DMA_CH1_CMD   = IO_STATE(R_DMA_CH1_CMD, cmd, start);
85 }
86
87 int
88 handle_network_read(void)
89 {
90   if (!(rx_descr2.status & d_eop)) {
91     return FALSE;
92   }
93
94   /* Even if wasn't to us, we must do this... */
95   rx_descr2.status = 0;
96   *R_DMA_CH1_FIRST = (udword)&rx_descr;
97
98   /* Was it to me? */
99   if (ntohl(rx_header.seq) == (seq+1)) { 
100     interface        = NETWORK;
101     last_timeout     = *R_TIMER_DATA >> IO_BITNR(R_TIMER_DATA, timer0);
102     nbr_read        += rx_descr2.hw_len - CRC_LEN;
103     rx_descr2.buf   += rx_descr2.hw_len - CRC_LEN;
104     rx_descr2.sw_len = bytes_to_read - nbr_read - CRC_LEN < 1500 ?
105       bytes_to_read - nbr_read + CRC_LEN: 1500;  /* FIX!!!!! */
106     rx_descr2.sw_len = rx_descr2.sw_len + NETWORK_HEADER_LENGTH < 64
107       ? 64 - NETWORK_HEADER_LENGTH : rx_descr2.sw_len; /* Less than minimum eth packet? */
108
109     seq++;
110     send_network_ack();
111   }
112
113   return TRUE;
114 }
115
116 void
117 send_network_ack(void)
118 {
119 /*  send_serial_string(">send_network_ack.\r\n"); */
120   
121   if (!set_dest) {    /* Copy destination address from first received packet */
122     set_dest = TRUE;
123     /* If we have done a bootrom network boot, source address is in a different
124        place... */
125     if (((*R_BUS_STATUS & IO_MASK(R_BUS_STATUS, boot))
126          >> IO_BITNR(R_BUS_STATUS, boot)) - 1 == NETWORK) {
127       *(udword*)&tx_header.dest[0] = *(udword*)0x380000dc;
128       *(uword*)&tx_header.dest[4]  = *(uword*)0x380000e0;
129     }
130     else {
131       *(udword*)&tx_header.dest[0] = *(udword*)&rx_header.src[0];
132       *(uword*)&tx_header.dest[4]  = *(uword*)&rx_header.src[4];
133     }
134   }
135
136 #if 1
137   tx_header.seq   = htonl(seq);
138   tx_header.type  = htonl(ACK);
139 #else
140   tx_header.seq   = htonl(seq);
141   tx_header.type  = htonl(bytes_to_read);
142   tx_header.id    = htonl(target_address);
143   /* tx_header.id already set in start(). */
144 #endif
145
146   tx_descr.ctrl   = TX_CTRL_EOP;
147   tx_descr.sw_len = NETWORK_HEADER_LENGTH;
148
149   start_network_trans();
150 }
151
152 void
153 start_network_trans(void)
154 {
155 /*  send_serial_string(">start_network_trans\r\n"); */
156   
157   /* Clear possible underrun or excessive retry errors */
158 /*  *R_NETWORK_TR_CTRL = */
159 /*    (IO_STATE (R_NETWORK_TR_CTRL, clr_error, clr)     | */
160 /*     IO_STATE (R_NETWORK_TR_CTRL, delay,     none)    | */
161 /*     IO_STATE (R_NETWORK_TR_CTRL, cancel,    dont)    | */
162 /*     IO_STATE (R_NETWORK_TR_CTRL, cd,        enable)  | */
163 /*     IO_STATE (R_NETWORK_TR_CTRL, pad,       enable)  | */
164 /*     IO_STATE (R_NETWORK_TR_CTRL, crc,       enable)  | */
165 /*     IO_STATE (R_NETWORK_TR_CTRL, retry,     enable)); */
166   
167   *R_DMA_CH0_FIRST = (udword)&tx_descr;
168   *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, start);
169   while(*R_DMA_CH0_FIRST)
170     ;
171 }
172
173 void 
174 send_network_string(char *str)
175 {
176   int i;
177
178   tx_descr.next   = (udword)&tx_descr2;
179   tx_descr.ctrl   = TX_CTRL;
180   for (i = 0; str[i]; i++)      /* strlen */
181     ;
182
183   tx_header.type   = STRING;
184
185   tx_descr2.ctrl   = TX_CTRL_EOP;
186   tx_descr2.buf    = (udword)str;
187   tx_descr2.sw_len = i+1;
188
189   start_network_trans();
190 }
191
192 void 
193 send_network_hex(udword v, byte nl)
194 {
195   tx_descr.next   = (udword)&tx_descr2;
196   tx_descr.ctrl   = TX_CTRL;
197
198   tx_header.type  = nl ? htonl(NET_INT_NL) : htonl(NET_INT);
199
200   /* Pause so we don't saturate network. */
201   /* Hehe, the asm will fool gcc to not remove the loop even though it
202      probably should. If we volatile i the code will be a few bytes
203      longer than this version. Well I really did it like this just
204      because it is possible... */
205   {
206     udword i;
207     
208     for(i = 0; i != 16384; i++)
209       __asm__ ("");             
210   }
211
212   v = htonl(v);
213   tx_descr2.ctrl   = TX_CTRL_EOP;
214   tx_descr2.buf    = (udword)&v;
215   tx_descr2.sw_len = (uword)sizeof(udword);
216
217   start_network_trans();
218 }