1 #include <rthw.h>
2 #include <rtthread.h>
3 #include <netif/ethernetif.h>
4 
5 #include "sam7x_emac.h"
6 #include "AT91SAM7X256.h"
7 #include "lwipopts.h"
8 #include "lwip/mem.h"
9 
10 #define MAX_ADDR_LEN 6
11 
12 #ifdef DM9161
13 #define EMAC_PIO_CFG	(AT91C_PB8_EMDC         | \
14 						 AT91C_PB9_EMDIO         | \
15 						 AT91C_PB2_ETX0          | \
16 						 AT91C_PB3_ETX1          | \
17 						 AT91C_PB10_ETX2         | \
18 						 AT91C_PB11_ETX3         | \
19 						 AT91C_PB1_ETXEN         | \
20 						 AT91C_PB0_ETXCK_EREFCK  | \
21 						 AT91C_PB15_ERXDV_ECRSDV | \
22 						 AT91C_PB5_ERX0			| \
23 						 AT91C_PB6_ERX1			| \
24 						 AT91C_PB12_ETXER        | \
25 						 AT91C_PB13_ERX2			| \
26 						 AT91C_PB14_ERX3			| \
27 						 AT91C_PB17_ERXCK		| \
28 						 AT91C_PB16_ECOL			| \
29 						 AT91C_PB4_ECRS			| \
30 						 AT91C_PB7_ERXER)
31 #else
32 #define EMAC_PIO_CFG	(AT91C_PB0_ETXCK_EREFCK | \
33 		AT91C_PB1_ETXEN        | \
34 		AT91C_PB2_ETX0         | \
35 		AT91C_PB3_ETX1         | \
36 		AT91C_PB4_ECRS         | \
37 		AT91C_PB5_ERX0         | \
38 		AT91C_PB6_ERX1         | \
39 		AT91C_PB7_ERXER        | \
40 		AT91C_PB8_EMDC         | \
41 		AT91C_PB9_EMDIO        | \
42 		AT91C_PB10_ETX2        | \
43 		AT91C_PB11_ETX3        | \
44 		AT91C_PB10_ETX2		   | \
45 		AT91C_PB13_ERX2        | \
46 		AT91C_PB14_ERX3        | \
47 		AT91C_PB15_ERXDV_ECRSDV| \
48 		AT91C_PB16_ECOL        | \
49 		AT91C_PB17_ERXCK)
50 #endif
51 
52 #define RB_BUFFER_SIZE		8			/* max number of receive buffers */
53 #define ETH_RX_BUF_SIZE		128
54 
55 #define TB_BUFFER_SIZE		4
56 #define ETH_TX_BUF_SIZE		(PBUF_POOL_BUFSIZE)
57 
58 struct rbf_t
59 {
60 	rt_uint32_t addr;
61 	rt_uint32_t status;
62 };
63 
64 static rt_uint32_t 	current_rb_index;						/* current receive buffer index */
65 static volatile struct rbf_t rb_descriptors[RB_BUFFER_SIZE];
66 static volatile struct rbf_t tb_descriptors[TB_BUFFER_SIZE];
67 static rt_uint8_t 	rx_buf[RB_BUFFER_SIZE][ETH_RX_BUF_SIZE] __attribute__ ((aligned (8)));
68 static rt_uint8_t 	tx_buf[TB_BUFFER_SIZE][ETH_TX_BUF_SIZE] __attribute__ ((aligned (8)));
69 static struct rt_semaphore tx_sem;
70 
71 struct net_device
72 {
73 	/* inherit from ethernet device */
74 	struct eth_device parent;
75 
76 	/* interface address info. */
77 	rt_uint8_t  dev_addr[MAX_ADDR_LEN];			/* hw address	*/
78 };
79 static struct net_device  sam7x_dev_entry;
80 static struct net_device *sam7x_dev =&sam7x_dev_entry;
81 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
82 
write_phy(rt_uint8_t addr,rt_uint32_t value)83 rt_inline void write_phy(rt_uint8_t addr, rt_uint32_t value)
84 {
85 	AT91C_BASE_EMAC->EMAC_MAN = ((0x01<<30) | (2 << 16) | (1 << 28) |
86 								 (AT91C_PHY_ADDR << 23) | (addr << 18))  | value;
87 	/* Wait until IDLE bit in Network Status register is cleared */
88 	while (!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
89 }
90 
read_phy(rt_uint8_t addr)91 rt_inline rt_uint32_t read_phy(rt_uint8_t addr)
92 {
93 	AT91C_BASE_EMAC->EMAC_MAN = (0x01<<30) | (0x02 << 16) | (0x02 << 28) |
94 								(AT91C_PHY_ADDR << 23) | (addr << 18);
95 
96 	/* Wait until IDLE bit in Network Status register is cleared */
97 	while (!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
98 
99 	return (AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff);
100 }
101 
sam7xether_reset_tx_desc(void)102 rt_inline void sam7xether_reset_tx_desc(void)
103 {
104 	static rt_uint32_t index = 0;
105 
106 	if(tb_descriptors[index].status & TxDESC_STATUS_USED)
107 	{
108 		while(!(tb_descriptors[index].status & TxDESC_STATUS_LAST_BUF))
109 		{
110 			index ++;
111 			if(index >= TB_BUFFER_SIZE)index = 0;
112 
113 			tb_descriptors[index].status |= TxDESC_STATUS_USED;
114 		}
115 
116 		index ++;
117 		if(index >= TB_BUFFER_SIZE)index = 0;
118 	}
119 }
120 
121 
122 /* interrupt service routing */
sam7xether_isr(int irq,void * param)123 static void sam7xether_isr(int irq, void* param)
124 {
125 	/* Variable definitions can be made now. */
126 	volatile rt_uint32_t isr, rsr;
127 
128 	/* get status */
129 	isr = AT91C_BASE_EMAC->EMAC_ISR;
130 	rsr = AT91C_BASE_EMAC->EMAC_RSR;
131 
132 	if( ( isr & AT91C_EMAC_RCOMP ) || ( rsr & AT91C_EMAC_REC ) )
133 	{
134 		rt_err_t result;
135 
136 		/* a frame has been received */
137 		result = eth_device_ready((struct eth_device*)&(sam7x_dev->parent));
138 		RT_ASSERT(result == RT_EOK);
139 
140 		AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_REC;
141 	}
142 
143 	if( isr & AT91C_EMAC_TCOMP )
144 	{
145 		/* A frame has been transmitted. Mark all the buffers as free */
146 		sam7xether_reset_tx_desc();
147 
148 		AT91C_BASE_EMAC->EMAC_TSR = AT91C_EMAC_COMP;
149 	}
150 }
151 
linksetup(void)152 rt_inline void linksetup(void)
153 {
154 	rt_uint32_t value, tout, id1, id2;
155 #ifdef DM9161
156 	rt_uint32_t ulBMSR,ulBMCR,i;
157 #endif
158 
159 #ifdef DM9161
160   	//PHY has internal pull down : disable MII isolate
161   	tout = read_phy(PHY_REG_BMCR);
162   	tout = read_phy(PHY_REG_BMCR);
163   	tout &= ~BMCR_ISOLATE;
164   	write_phy(PHY_REG_BMCR, tout);
165 
166 	/* Check if this is a RTL8201 or DM9161 PHY. */
167 	id1 = read_phy(PHY_REG_PHYID1);
168 	id2 = read_phy(PHY_REG_PHYID2);
169 
170 	if (((id1 << 16) | (id2 & 0xfff0)) == MII_DM9161_ID)
171 	{
172 		rt_kprintf("read MII_DM9161_ID ok!\n");
173 
174         tout = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
175                DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
176         write_phy(PHY_REG_ANAR, tout);
177    	    // Wait for PHY auto negotiation completed
178 		i = 0;
179   	    do {
180     		ulBMSR = read_phy(PHY_REG_BMSR);
181 			ulBMSR = read_phy(PHY_REG_BMSR);
182 			i++;
183 
184 			if(i >= 0xffff)
185 			   break;
186   	    }while (!(ulBMSR & BMSR_ANEGCOMPLETE));
187 
188 		if(i >= 0xffff)
189 		   rt_kprintf("PHY No Link!\n");
190 		else
191 		   rt_kprintf("PHY auto negotiation completed!\n");
192 
193 		/* Update the MAC register NCFGR. */
194 		AT91C_BASE_EMAC->EMAC_NCFGR = 0;
195 		ulBMCR = read_phy(PHY_REG_BMCR);
196 
197 	    if (ulBMCR & BMCR_ANENABLE)
198 	    {
199 			/* AutoNegotiation is enabled. */
200 			if(!(ulBMSR & BMSR_ANEGCOMPLETE))
201 			{
202 			    /* Auto-negotitation in progress. */
203 				rt_kprintf("Auto-negotitation in progress!\n");
204 			    return;
205 			}
206 
207 	    	if (ulBMCR & BMCR_SPEED100)
208 	    	{
209 		    	/* Speed 100Mbit is enabled. */
210 		    	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_SPD;
211 
212 	    	}
213 	    	if (ulBMCR & BMCR_FULLDPLX)
214 	    	{
215 		    	/* Full duplex is enabled. */
216 		    	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_FD;
217 	    	}
218        }
219     }
220 #else
221 	/* Check if this is a RTL8201 or DM9161 PHY. */
222 	id1 = read_phy(PHY_REG_PHYID1);
223 	id2 = read_phy(PHY_REG_PHYID2);
224 
225 	if (((id2 << 16) | (id1 & 0xfff0)) == MII_RTL8201_ID)
226 	{
227 	    rt_kprintf("read MII_RTL8201_ID ok!\n");
228 
229 
230 		/* Configure the PHY device */
231 		/* Use autonegotiation about the link speed. */
232 		write_phy (PHY_REG_BMCR, PHY_AUTO_NEG);
233 
234 		/* Wait to complete Auto_Negotiation. */
235 		for (tout = 0; tout < 0x100000; tout++)
236 		{
237 			value = read_phy (PHY_REG_BMSR);
238 			if (value & BMSR_ANEGCOMPLETE) break; /* autonegotiation finished. */
239 		}
240 
241 		/* Check the link status. */
242 		for (tout = 0; tout < 0x10000; tout++)
243 		{
244 			value = read_phy (PHY_REG_BMSR);
245 			if (value & BMSR_LINKST) break; /* Link is on. */
246 		}
247 	}
248 	value = read_phy (PHY_REG_ANLPAR);
249 
250 	/* Update the MAC register NCFGR. */
251 	AT91C_BASE_EMAC->EMAC_NCFGR &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
252 
253 	/* set full duplex . */
254 	if (value & 0xA000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_FD;
255 	/* set speed */
256 	if (value & 0xC000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_SPD;
257  #endif
258 }
259 
260 /*
261  * Set the MAC address.
262  */
update_mac_address(struct net_device * device)263 rt_inline void update_mac_address(struct net_device* device)
264 {
265 	AT91C_BASE_EMAC->EMAC_SA1L = (device->dev_addr[3] << 24) |
266 								 (device->dev_addr[2] << 16) |
267 								 (device->dev_addr[1] << 8)  |
268 								 device->dev_addr[0];
269 	AT91C_BASE_EMAC->EMAC_SA1H = (device->dev_addr[5] << 8) |
270 								 device->dev_addr[4];
271 }
272 
sam7xether_desc_init()273 rt_inline void sam7xether_desc_init()
274 {
275 	rt_uint32_t i;
276 
277 	/* Rx Buffer Descriptor initialization */
278 	current_rb_index = 0;
279 	for (i = 0; i < RB_BUFFER_SIZE; i++)
280 	{
281 		rb_descriptors[i].addr = (rt_uint32_t)&(rx_buf[i][0]);
282 		rb_descriptors[i].status = 0;
283 	}
284 	/* Set the WRAP bit at the end of the list descriptor. */
285 	rb_descriptors[RB_BUFFER_SIZE-1].addr |= 0x02;
286 	/* Set Rx Queue pointer to descriptor list. */
287 	AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int)&(rb_descriptors[0]);
288 
289 	/* Tx Buffer Descriptor initialization */
290 	for (i = 0; i < TB_BUFFER_SIZE; i++)
291 	{
292 		tb_descriptors[i].addr = (rt_uint32_t)&(tx_buf[i][0]);
293 		tb_descriptors[i].status = TxDESC_STATUS_USED;
294 	}
295 	/* Set the WRAP bit at the end of the list descriptor. */
296 	tb_descriptors[TB_BUFFER_SIZE-1].status |= TxDESC_STATUS_WRAP;
297 	/* Set Tx Queue pointer to descriptor list. */
298 	AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int)&(tb_descriptors[0]);
299 }
300 
301 /* RT-Thread Device Interface */
302 
303 /* initialize the interface */
sam7xether_init(rt_device_t dev)304 rt_err_t sam7xether_init(rt_device_t dev)
305 {
306 	rt_uint32_t i;
307 
308 	/* enable peripheral clock for EMAC and PIO B */
309 	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB | 1 << AT91C_ID_EMAC;
310 
311 	/* Disable pull up on RXDV => PHY normal mode (not in test mode), */
312 	/* and set MII mode. PHY has internal pull down.                  */
313 	AT91C_BASE_PIOB->PIO_PPUDR = (1<<16) | (1 << 15);
314 
315 	/* Clear PB18 <=> PHY powerdown */
316 	AT91C_BASE_PIOB->PIO_PER 	= 1<<18;
317 	AT91C_BASE_PIOB->PIO_OER 	= 1<<18;
318 	AT91C_BASE_PIOB->PIO_CODR 	= 1<<18;
319 
320 	/* EMAC IO init for EMAC-PHY communication. */
321 	AT91C_BASE_PIOB->PIO_ASR = EMAC_PIO_CFG;
322 	AT91C_BASE_PIOB->PIO_PDR = EMAC_PIO_CFG; // Set in Periph mode
323 
324 	/* Enable communication between EMAC-PHY. */
325 	AT91C_BASE_EMAC->EMAC_NCR   |= AT91C_EMAC_MPE;
326 	/* MDC = MCK/32 */
327 	AT91C_BASE_EMAC->EMAC_NCFGR |= 2<<10;
328 
329 	/* Reset PHY */
330 	AT91C_BASE_PIOB->PIO_PPUDR = AT91C_PB7_ERXER;
331 
332 	AT91C_BASE_RSTC->RSTC_RMR = 0xA5000000 | (0x08 << 8) ;
333 	AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
334 
335 	i = 0;
336 	while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL))
337 	{
338 	   i++;
339 	   if(i >= 0xfffff)
340 	     break;
341 	}
342 
343     for(i=0; i<0xfffff; i++);//* �ȴ�һ��ָ����ʱ�䣬ʹPHY����
344 
345 	linksetup();
346 
347 	rt_kprintf("linksetup ok!\n");
348 
349 	/* Disable management port in MAC control register. */
350 	AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
351 
352 	/* Enable EMAC in MII mode, enable clock ERXCK and ETXCK */
353 	AT91C_BASE_EMAC->EMAC_USRIO= AT91C_EMAC_CLKEN;
354 
355 	/* Transmit and Receive disable. */
356 	AT91C_BASE_EMAC->EMAC_NCR &= ~(AT91C_EMAC_RE | AT91C_EMAC_TE);
357 
358 	/* init descriptor */
359 	sam7xether_desc_init();
360 
361 	/* Clear receive and transmit status registers. */
362 	AT91C_BASE_EMAC->EMAC_RSR  = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
363 	AT91C_BASE_EMAC->EMAC_TSR  = (AT91C_EMAC_UND | AT91C_EMAC_COMP| AT91C_EMAC_BEX |
364 								  AT91C_EMAC_RLES| AT91C_EMAC_COL | AT91C_EMAC_UBR);
365 
366 	/* Configure EMAC operation mode. */
367 	//AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_BIG | AT91C_EMAC_DRFCS);
368  	//                   ����������Ч֡�����ջ�����   *������FCS�ֶ�       �����չ㲥֡    ������1526�ֽڳ�֡
369 	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF |AT91C_EMAC_DRFCS | AT91C_EMAC_NBC | AT91C_EMAC_BIG;
370 	AT91C_BASE_EMAC->EMAC_NCR   |= (AT91C_EMAC_TE  | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
371 
372 	/* update MAC address */
373 	update_mac_address(sam7x_dev);
374 
375 	/* enable interrupt */
376 	AT91C_BASE_EMAC->EMAC_IDR = 0x3fff;
377 	AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
378 
379 	/* setup interrupt */
380 	rt_hw_interrupt_install(AT91C_ID_EMAC, sam7xether_isr, RT_NULL, "emac");
381 	*(volatile unsigned int*)(0xFFFFF000 + AT91C_ID_EMAC * 4) = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
382 	// AT91C_AIC_SMR(AT91C_ID_EMAC) = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
383 	rt_hw_interrupt_umask(AT91C_ID_EMAC);
384 
385 	return RT_EOK;
386 }
387 
388 /* control the interface */
sam7xether_control(rt_device_t dev,int cmd,void * args)389 rt_err_t sam7xether_control(rt_device_t dev, int cmd, void *args)
390 {
391 	switch(cmd)
392 	{
393 	case NIOCTL_GADDR:
394 		/* get mac address */
395 		if(args) rt_memcpy(args, sam7x_dev_entry.dev_addr, 6);
396 		else return -RT_ERROR;
397 		break;
398 
399 	default :
400 		break;
401 	}
402 
403 	return RT_EOK;
404 }
405 
406 /* Open the ethernet interface */
sam7xether_open(rt_device_t dev,rt_uint16_t oflags)407 rt_err_t sam7xether_open(rt_device_t dev, rt_uint16_t oflags)
408 {
409 	return RT_EOK;
410 }
411 
412 /* Close the interface */
sam7xether_close(rt_device_t dev)413 rt_err_t sam7xether_close(rt_device_t dev)
414 {
415 	return RT_EOK;
416 }
417 
418 /* Read */
sam7xether_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)419 rt_size_t sam7xether_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
420 {
421 	rt_set_errno(-RT_ENOSYS);
422 	return 0;
423 }
424 
425 /* Write */
sam7xether_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)426 rt_size_t sam7xether_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
427 {
428 	rt_set_errno(-RT_ENOSYS);
429 	return 0;
430 }
431 
432 /* See the header file for descriptions of public functions. */
sam7xether_write_frame(rt_uint8_t * ptr,rt_uint32_t length,rt_bool_t eof)433 void sam7xether_write_frame(rt_uint8_t *ptr, rt_uint32_t length, rt_bool_t eof)
434 {
435 	rt_uint8_t *buf_ptr;
436 	static rt_uint32_t current_tb_index = 0;
437 	rt_uint32_t is_last, tx_offset = 0, remain, pdu_length;
438 
439 	while(tx_offset < length)
440 	{
441 		/* check whether buffer is available */
442 		while(!(tb_descriptors[current_tb_index].status & TxDESC_STATUS_USED))
443 		{
444 			/* no buffer */
445 			rt_thread_delay(5);
446 		}
447 
448 		/* Get the address of the buffer from the descriptor, then copy
449 		the data into the buffer. */
450 		buf_ptr = (rt_uint8_t *)tb_descriptors[current_tb_index].addr;
451 
452 		/* How much can we write to the buffer? */
453 		remain = length - tx_offset;
454 		pdu_length = (remain <= ETH_TX_BUF_SIZE)? remain : ETH_TX_BUF_SIZE;
455 
456 		/* Copy the data into the buffer. */
457 		rt_memcpy(buf_ptr, &ptr[tx_offset], pdu_length );
458 		tx_offset += pdu_length;
459 
460 		/* Is this the last data for the frame? */
461 		if((eof == RT_TRUE) && ( tx_offset >= length )) is_last = TxDESC_STATUS_LAST_BUF;
462 		else is_last = 0;
463 
464 		/* Fill out the necessary in the descriptor to get the data sent,
465 		then move to the next descriptor, wrapping if necessary. */
466 		if(current_tb_index >= (TB_BUFFER_SIZE - 1))
467 		{
468 			tb_descriptors[current_tb_index].status = ( pdu_length & TxDESC_STATUS_BUF_SIZE )
469 					| is_last
470 					| TxDESC_STATUS_WRAP;
471 			current_tb_index = 0;
472 		}
473 		else
474 		{
475 			tb_descriptors[current_tb_index].status = ( pdu_length & TxDESC_STATUS_BUF_SIZE )
476 					| is_last;
477 			current_tb_index++;
478 		}
479 
480 		/* If this is the last buffer to be sent for this frame we can
481 		start the transmission. */
482 		if(is_last)
483 		{
484 			AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
485 		}
486 	}
487 }
488 
489 /* ethernet device interface */
490 /*
491  * Transmit packet.
492  */
sam7xether_tx(rt_device_t dev,struct pbuf * p)493 rt_err_t sam7xether_tx( rt_device_t dev, struct pbuf* p)
494 {
495 	struct pbuf* q;
496 
497 	/* lock tx operation */
498 	rt_sem_take(&tx_sem, RT_WAITING_FOREVER);
499 
500 	for (q = p; q != NULL; q = q->next)
501 	{
502 		if (q->next == RT_NULL) sam7xether_write_frame(q->payload, q->len, RT_TRUE);
503 		else sam7xether_write_frame(q->payload, q->len, RT_FALSE);
504 	}
505 
506 	rt_sem_release(&tx_sem);
507 
508 	return 0;
509 }
510 
sam7xether_read_frame(rt_uint8_t * ptr,rt_uint32_t section_length,rt_uint32_t total)511 void sam7xether_read_frame(rt_uint8_t* ptr, rt_uint32_t section_length, rt_uint32_t total)
512 {
513 	static rt_uint8_t* src_ptr;
514 	register rt_uint32_t buf_remain, section_remain;
515 	static rt_uint32_t section_read = 0, buf_offset = 0, frame_read = 0;
516 
517 	if(ptr == RT_NULL)
518 	{
519 		/* Reset our state variables ready for the next read from this buffer. */
520 		src_ptr = (rt_uint8_t *)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
521 		frame_read = (rt_uint32_t)0;
522 		buf_offset = (rt_uint32_t)0;
523 	}
524 	else
525 	{
526 		/* Loop until we have obtained the required amount of data. */
527 		section_read = 0;
528 		while( section_read < section_length )
529 		{
530 			buf_remain = (ETH_RX_BUF_SIZE - buf_offset);
531 			section_remain = section_length - section_read;
532 
533 			if( section_remain > buf_remain )
534 			{
535 				/* more data on section than buffer size */
536 				rt_memcpy(&ptr[ section_read ], &src_ptr[buf_offset], buf_remain);
537 				section_read += buf_remain;
538 				frame_read += buf_remain;
539 
540 				/* free buffer */
541 				rb_descriptors[current_rb_index].addr &= ~RxDESC_FLAG_OWNSHIP;
542 
543 				/* move to the next frame. */
544 				current_rb_index++;
545 				if(current_rb_index >= RB_BUFFER_SIZE) current_rb_index = 0;
546 
547 				/* Reset the variables for the new buffer. */
548 				src_ptr = (rt_uint8_t *)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
549 				buf_offset = 0;
550 			}
551 			else
552 			{
553 				/* more data on buffer than section size */
554 				rt_memcpy(&ptr[section_read], &src_ptr[buf_offset], section_remain);
555 				buf_offset += section_remain;
556 				section_read += section_remain;
557 				frame_read += section_remain;
558 
559 				/* finish this read */
560 				if((buf_offset >= ETH_RX_BUF_SIZE) || (frame_read >= total))
561 				{
562 					/* free buffer */
563 					rb_descriptors[current_rb_index].addr &= ~(RxDESC_FLAG_OWNSHIP);
564 
565 					/* move to the next frame. */
566 					current_rb_index++;
567 					if( current_rb_index >= RB_BUFFER_SIZE ) current_rb_index = 0;
568 
569 					src_ptr = (rt_uint8_t*)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
570 					buf_offset = 0;
571 				}
572 			}
573 		}
574 	}
575 }
576 
sam7xether_rx(rt_device_t dev)577 struct pbuf *sam7xether_rx(rt_device_t dev)
578 {
579 	struct pbuf *p = RT_NULL;
580 
581 	/* skip fragment frame */
582 	while((rb_descriptors[current_rb_index].addr & RxDESC_FLAG_OWNSHIP)
583 			&& !(rb_descriptors[current_rb_index].status & RxDESC_STATUS_FRAME_START))
584 	{
585 		rb_descriptors[current_rb_index].addr &= (~RxDESC_FLAG_OWNSHIP);
586 
587 		current_rb_index++;
588 		if(current_rb_index >= RB_BUFFER_SIZE) current_rb_index = 0;
589 	}
590 
591 	if ((rb_descriptors[current_rb_index].addr & RxDESC_FLAG_OWNSHIP))
592 	{
593 		struct pbuf* q;
594 		rt_uint32_t index, pkt_len = 0;
595 
596 		/* first of all, find the frame length */
597 		index = current_rb_index;
598 		while (rb_descriptors[index].addr & RxDESC_FLAG_OWNSHIP)
599 		{
600 			pkt_len = rb_descriptors[index].status & RxDESC_STATUS_BUF_SIZE;
601 			if (pkt_len > 0) break;
602 
603 			index ++;
604 			if (index >= RB_BUFFER_SIZE) index = 0;
605 		}
606 
607 		if (pkt_len)
608 		{
609 			//p = pbuf_alloc(PBUF_LINK, pkt_len, PBUF_RAM);
610 			p = pbuf_alloc(PBUF_RAW, pkt_len, PBUF_POOL);
611 			if(p != RT_NULL)
612 			{
613 				sam7xether_read_frame(RT_NULL, 0, pkt_len);
614 				for(q = p; q != RT_NULL; q= q->next)
615 					sam7xether_read_frame(q->payload, q->len, pkt_len);
616 			}
617 			else
618 			{
619 				rt_kprintf("no memory in pbuf\n");
620 			}
621 		}
622 	}
623 
624 	/* enable interrupt */
625 	AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP;
626 
627 	return p;
628 }
629 
sam7xether_register(char * name)630 int sam7xether_register(char *name)
631 {
632 	rt_err_t result;
633 
634 	/* init rt-thread device interface */
635 	sam7x_dev_entry.parent.parent.init		= sam7xether_init;
636 	sam7x_dev_entry.parent.parent.open		= sam7xether_open;
637 	sam7x_dev_entry.parent.parent.close		= sam7xether_close;
638 	sam7x_dev_entry.parent.parent.read		= sam7xether_read;
639 	sam7x_dev_entry.parent.parent.write		= sam7xether_write;
640 	sam7x_dev_entry.parent.parent.control	= sam7xether_control;
641 	sam7x_dev_entry.parent.eth_rx			= sam7xether_rx;
642 	sam7x_dev_entry.parent.eth_tx			= sam7xether_tx;
643 
644 	/* Update MAC address */
645 	sam7x_dev_entry.dev_addr[0] = 0x1e;
646 	sam7x_dev_entry.dev_addr[1] = 0x30;
647 	sam7x_dev_entry.dev_addr[2] = 0x6c;
648 	sam7x_dev_entry.dev_addr[3] = 0xa2;
649 	sam7x_dev_entry.dev_addr[4] = 0x45;
650 	sam7x_dev_entry.dev_addr[5] = 0x5e;
651 	/* update mac address */
652 	update_mac_address(sam7x_dev);
653 
654 	rt_sem_init(&tx_sem, "emac", 1, RT_IPC_FLAG_FIFO);
655 
656 	result = eth_device_init(&(sam7x_dev->parent), (char*)name);
657 	RT_ASSERT(result == RT_EOK);
658 
659 	return RT_EOK;
660 }
661