?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file ax88796.c \brief ASIX AX88796 Ethernet Interface Driver. */
2 //*****************************************************************************
3 //
4 // File Name : 'ax88796.c'
5 // Title : ASIX AX88796 Ethernet Interface Driver
6 // Author : Pascal Stang
7 // Created : 10/22/2002
8 // Revised : 8/21/2005
9 // Version : 0.1
10 // Target MCU : Atmel AVR series
11 // Editor Tabs : 4
12 //
13 // Description : This driver provides initialization and transmit/receive
14 // functions for the ASIX AX88796 10/100Mb Ethernet Controller and PHY.
15 //
16 // Based in part on code by Louis Beaudoin (www.embedded-creations.com).
17 // Thanks to Adam Dunkels and Louis Beaudoin for providing the initial
18 // structure in which to write this driver.
19 //
20 //*****************************************************************************
21  
22 #include "global.h"
23 #include "timer.h"
24 #include "rprintf.h"
25  
26 #include "ax88796.h"
27  
28 // include configuration
29 #include "ax88796conf.h"
30  
31 // pointers to locations in the ax88796 receive buffer
32 static unsigned char NextPage; // page pointer to next Rx packet
33 static unsigned int CurrentRetreiveAddress; // DMA address for read Rx packet location
34  
35  
36 void nicInit(void)
37 {
38 ax88796Init();
39 }
40  
41 void nicSend(unsigned int len, unsigned char* packet)
42 {
43 ax88796BeginPacketSend(len);
44 ax88796SendPacketData(packet, len);
45 ax88796EndPacketSend();
46 }
47  
48 unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
49 {
50 unsigned int packetLength;
51  
52 packetLength = ax88796BeginPacketRetreive();
53  
54 // if there's no packet or an error - exit without ending the operation
55 if( !packetLength )
56 return 0;
57  
58 // drop anything too big for the buffer
59 if( packetLength > maxlen )
60 {
61 ax88796EndPacketRetreive();
62 return 0;
63 }
64  
65 // copy the packet data into the uIP packet buffer
66 ax88796RetreivePacketData( packet, packetLength );
67 ax88796EndPacketRetreive();
68  
69 return packetLength;
70 }
71  
72 void nicGetMacAddress(u08* macaddr)
73 {
74 u08 tempCR;
75 // switch register pages
76 tempCR = ax88796Read(CR);
77 ax88796Write(CR,tempCR|PS0);
78 // read MAC address registers
79 *macaddr++ = ax88796Read(PAR0);
80 *macaddr++ = ax88796Read(PAR1);
81 *macaddr++ = ax88796Read(PAR2);
82 *macaddr++ = ax88796Read(PAR3);
83 *macaddr++ = ax88796Read(PAR4);
84 *macaddr++ = ax88796Read(PAR5);
85 // switch register pages back
86 ax88796Write(CR,tempCR);
87 }
88  
89 void nicSetMacAddress(u08* macaddr)
90 {
91 u08 tempCR;
92 // switch register pages
93 tempCR = ax88796Read(CR);
94 ax88796Write(CR,tempCR|PS0);
95 // write MAC address registers
96 ax88796Write(PAR0, *macaddr++);
97 ax88796Write(PAR1, *macaddr++);
98 ax88796Write(PAR2, *macaddr++);
99 ax88796Write(PAR3, *macaddr++);
100 ax88796Write(PAR4, *macaddr++);
101 ax88796Write(PAR5, *macaddr++);
102 // switch register pages back
103 ax88796Write(CR,tempCR);
104 }
105  
106 void nicRegDump(void)
107 {
108 ax88796RegDump();
109 }
110  
111  
112 void ax88796SetupPorts(void)
113 {
114 #if NIC_CONNECTION == MEMORY_MAPPED
115 // enable external SRAM interface - no wait states
116 sbi(MCUCR, SRE);
117 // sbi(MCUCR, SRW10);
118 // sbi(XMCRA, SRW00);
119 // sbi(XMCRA, SRW01);
120 // sbi(XMCRA, SRW11);
121 #else
122 // set address port to output
123 AX88796_ADDRESS_DDR = AX88796_ADDRESS_MASK;
124  
125 // set data port to input with pull-ups
126 AX88796_DATA_DDR = 0x00;
127 AX88796_DATA_PORT = 0xFF;
128  
129 // initialize the control port read and write pins to de-asserted
130 sbi( AX88796_CONTROL_PORT, AX88796_CONTROL_READPIN );
131 sbi( AX88796_CONTROL_PORT, AX88796_CONTROL_WRITEPIN );
132 // set the read and write pins to output
133 sbi( AX88796_CONTROL_DDR, AX88796_CONTROL_READPIN );
134 sbi( AX88796_CONTROL_DDR, AX88796_CONTROL_WRITEPIN );
135 #endif
136 // set reset pin to output
137 sbi( AX88796_RESET_DDR, AX88796_RESET_PIN );
138 }
139  
140  
141 #if NIC_CONNECTION == MEMORY_MAPPED
142 inline void ax88796Write(u08 address, u08 data)
143 {
144 *(volatile u08*)(AX88796_MEMORY_MAPPED_OFFSET + address) = data;
145 }
146 #else
147 void ax88796Write(u08 address, u08 data)
148 {
149 // assert the address
150 AX88796_ADDRESS_PORT = address | (AX88796_ADDRESS_PORT&~AX88796_ADDRESS_MASK);
151  
152 // set data bus as output and place data on bus
153 AX88796_DATA_DDR = 0xFF;
154 AX88796_DATA_PORT = data;
155  
156 // clock write pin
157 cbi(AX88796_CONTROL_PORT, AX88796_CONTROL_WRITEPIN);
158 nop();
159 nop();
160 sbi(AX88796_CONTROL_PORT, AX88796_CONTROL_WRITEPIN);
161  
162 // set data bus back to input with pullups enabled
163 AX88796_DATA_DDR = 0x00;
164 AX88796_DATA_PORT = 0xFF;
165 }
166 #endif
167  
168  
169 #if NIC_CONNECTION == MEMORY_MAPPED
170 inline u08 ax88796Read(u08 address)
171 {
172 return *(volatile u08*)(AX88796_MEMORY_MAPPED_OFFSET + address);
173 }
174 #else
175 u08 ax88796Read(u08 address)
176 {
177 u08 data;
178  
179 // assert the address
180 AX88796_ADDRESS_PORT = address | (AX88796_ADDRESS_PORT&~AX88796_ADDRESS_MASK);
181  
182 // assert read
183 cbi(AX88796_CONTROL_PORT, AX88796_CONTROL_READPIN);
184 nop();
185 nop();
186 // read in the data
187 data = AX88796_DATA_PIN;
188  
189 // negate read
190 sbi(AX88796_CONTROL_PORT, AX88796_CONTROL_READPIN);
191  
192 return data;
193 }
194 #endif
195  
196  
197 void ax88796Init(void)
198 {
199 unsigned char tcrFduFlag;
200  
201 // initialize I/O ports
202 ax88796SetupPorts();
203  
204 // do a hard reset
205 sbi(AX88796_RESET_PORT, AX88796_RESET_PIN);
206 delay_ms(100);
207 cbi(AX88796_RESET_PORT, AX88796_RESET_PIN);
208  
209 // do soft reset
210 ax88796Write(ISR, ax88796Read(ISR));
211 delay_ms(50);
212  
213 // wait for PHY to come out of reset
214 ax88796Read(RSTPORT);
215 while(ax88796Read(TR) & RST_B);
216  
217 ax88796WriteMii(0x10,0x00,0x0800);
218 delay_ms(255);
219 ax88796WriteMii(0x10,0x00,0x1200);
220  
221 ax88796Write(CR,(RD2|STOP)); // stop the NIC, abort DMA, page 0
222 delay_ms(5); // make sure nothing is coming in or going out
223 ax88796Write(DCR,DCR_INIT);
224 ax88796Write(RBCR0,0x00);
225 ax88796Write(RBCR1,0x00);
226 ax88796Write(IMR,0x00);
227 ax88796Write(ISR,0xFF);
228 ax88796Write(RCR,0x20);
229 ax88796Write(BNRY,RXSTART_INIT);
230 ax88796Write(PSTART,RXSTART_INIT);
231 ax88796Write(PSTOP,RXSTOP_INIT);
232  
233 // switch to page 1
234 ax88796Write(CR,(PS0|RD2|STOP));
235 // write mac address
236 ax88796Write(PAR0+0, AX88796_MAC0);
237 ax88796Write(PAR0+1, AX88796_MAC1);
238 ax88796Write(PAR0+2, AX88796_MAC2);
239 ax88796Write(PAR0+3, AX88796_MAC3);
240 ax88796Write(PAR0+4, AX88796_MAC4);
241 ax88796Write(PAR0+5, AX88796_MAC5);
242 // set start point
243 ax88796Write(CURR,RXSTART_INIT+1);
244  
245 ax88796Write(CR,(RD2|START));
246 ax88796Write(RCR,RCR_INIT);
247  
248 if(ax88796Read(GPI) & I_SPD) // check PHY speed setting
249 tcrFduFlag = FDU; // if 100base, do full duplex
250 else
251 tcrFduFlag = 0; // if 10base, do half duplex
252  
253 ax88796Write(TCR,(tcrFduFlag|TCR_INIT));
254  
255 ax88796Write(GPOC,MPSEL); // select media interface
256  
257 ax88796Write(TPSR,TXSTART_INIT);
258  
259 ax88796Write(CR,(RD2|STOP));
260 ax88796Write(DCR,DCR_INIT);
261 ax88796Write(CR,(RD2|START));
262 ax88796Write(ISR,0xFF);
263 ax88796Write(IMR,IMR_INIT);
264 ax88796Write(TCR,(tcrFduFlag|TCR_INIT));
265  
266 //test
267 /*
268 while(1)
269 {
270 vt100SetCursorPos(18,0);
271 ax88796RegDump();
272 }
273 */
274 }
275  
276  
277 void ax88796BeginPacketSend(unsigned int packetLength)
278 {
279 unsigned int sendPacketLength;
280 sendPacketLength = (packetLength>=ETHERNET_MIN_PACKET_LENGTH)?
281 (packetLength):(ETHERNET_MIN_PACKET_LENGTH);
282  
283 //start the NIC
284 ax88796Write(CR,(RD2|START));
285  
286 // still transmitting a packet - wait for it to finish
287 while( ax88796Read(CR) & TXP );
288  
289 //load beginning page for transmit buffer
290 ax88796Write(TPSR,TXSTART_INIT);
291  
292 //set start address for remote DMA operation
293 ax88796Write(RSAR0,0x00);
294 ax88796Write(RSAR1,0x40);
295  
296 //clear the packet stored interrupt
297 ax88796Write(ISR, PTX);
298  
299 //load data byte count for remote DMA
300 ax88796Write(RBCR0, (unsigned char)(packetLength));
301 ax88796Write(RBCR1, (unsigned char)(packetLength>>8));
302  
303 ax88796Write(TBCR0, (unsigned char)(sendPacketLength));
304 ax88796Write(TBCR1, (unsigned char)((sendPacketLength)>>8));
305  
306 //do remote write operation
307 ax88796Write(CR,0x12);
308 }
309  
310  
311 void ax88796SendPacketData(unsigned char * localBuffer, unsigned int length)
312 {
313 unsigned int i;
314  
315 for(i=0;i<length;i++)
316 ax88796Write(RDMAPORT, localBuffer[i]);
317 }
318  
319  
320 void ax88796EndPacketSend(void)
321 {
322 //send the contents of the transmit buffer onto the network
323 ax88796Write(CR,(RD2|TXP));
324  
325 // clear the remote DMA interrupt
326 ax88796Write(ISR, RDC);
327 }
328  
329  
330 unsigned int ax88796BeginPacketRetreive(void)
331 {
332 unsigned char writePagePtr;
333 unsigned char readPagePtr;
334 unsigned char bnryPagePtr;
335 unsigned char i;
336  
337 unsigned char pageheader[4];
338 unsigned int rxlen;
339  
340 // check for and handle an overflow
341 ax88796ProcessInterrupt();
342  
343 // read CURR from page 1
344 ax88796Write(CR,(PS0|RD2|START));
345 writePagePtr = ax88796Read(CURR);
346 // read the boundary register from page 0
347 ax88796Write(CR,(RD2|START));
348 bnryPagePtr = ax88796Read(BNRY);
349  
350 // first packet is at page bnryPtr+1
351 readPagePtr = bnryPagePtr+1;
352 if(readPagePtr >= RXSTOP_INIT) readPagePtr = RXSTART_INIT;
353  
354 // return if there is no packet in the buffer
355 if( readPagePtr == writePagePtr )
356 {
357 return 0;
358 }
359  
360 // clear the packet received interrupt flag
361 ax88796Write(ISR, PRX);
362  
363 // if the boundary pointer is invalid,
364 // reset the contents of the buffer and exit
365 if( (bnryPagePtr < RXSTART_INIT) || (bnryPagePtr >= RXSTOP_INIT) )
366 {
367 ax88796Write(BNRY, RXSTART_INIT);
368 ax88796Write(CR, (PS0|RD2|START));
369 ax88796Write(CURR, RXSTART_INIT+1);
370 ax88796Write(CR, (RD2|START));
371  
372 // rprintf("B");
373 return 0;
374 }
375  
376 // initiate DMA to transfer the RTL8019 packet header
377 ax88796Write(RBCR0, 4);
378 ax88796Write(RBCR1, 0);
379 ax88796Write(RSAR0, 0);
380 ax88796Write(RSAR1, readPagePtr);
381 ax88796Write(CR, (RD0|START));
382 for(i=0;i<4;i++)
383 pageheader[i] = ax88796Read(RDMAPORT);
384  
385 // end the DMA operation
386 ax88796Write(CR, (RD2|START));
387 for(i = 0; i <= 20; i++)
388 if(ax88796Read(ISR) & RDC)
389 break;
390 ax88796Write(ISR, RDC);
391  
392 rxlen = (pageheader[PKTHEADER_PKTLENH]<<8) + pageheader[PKTHEADER_PKTLENL];
393 NextPage = pageheader[PKTHEADER_NEXTPAGE];
394  
395 CurrentRetreiveAddress = (readPagePtr<<8) + 4;
396  
397 // if the NextPage pointer is invalid, the packet is not ready yet - exit
398 if( (NextPage >= RXSTOP_INIT) || (NextPage < RXSTART_INIT) )
399 {
400 // rprintf("N");
401 // rprintfu08(nextPage);
402 return 0;
403 }
404  
405 return rxlen-4;
406 }
407  
408  
409 void ax88796RetreivePacketData(unsigned char * localBuffer, unsigned int length)
410 {
411 unsigned int i;
412  
413 // initiate DMA to transfer the data
414 ax88796Write(RBCR0, (unsigned char)length);
415 ax88796Write(RBCR1, (unsigned char)(length>>8));
416 ax88796Write(RSAR0, (unsigned char)CurrentRetreiveAddress);
417 ax88796Write(RSAR1, (unsigned char)(CurrentRetreiveAddress>>8));
418 ax88796Write(CR, (RD0|START));
419 for(i=0;i<length;i++)
420 localBuffer[i] = ax88796Read(RDMAPORT);
421  
422 // end the DMA operation
423 ax88796Write(CR, (RD2|START));
424 for(i = 0; i <= 20; i++)
425 if(ax88796Read(ISR) & RDC)
426 break;
427 ax88796Write(ISR, RDC);
428  
429 CurrentRetreiveAddress += length;
430 if( CurrentRetreiveAddress >= 0x6000 )
431 CurrentRetreiveAddress -= (0x6000-0x4600) ;
432 }
433  
434  
435 void ax88796EndPacketRetreive(void)
436 {
437 unsigned char i;
438 unsigned char bnryPagePtr;
439  
440 // end the DMA operation
441 ax88796Write(CR, (RD2|START));
442 for(i = 0; i <= 20; i++)
443 if(ax88796Read(ISR) & RDC)
444 break;
445 ax88796Write(ISR, RDC);
446  
447 // set the boundary register to point
448 // to the start of the next packet-1
449 bnryPagePtr = NextPage-1;
450 if(bnryPagePtr < RXSTART_INIT) bnryPagePtr = RXSTOP_INIT-1;
451  
452 ax88796Write(BNRY, bnryPagePtr);
453 }
454  
455  
456 void ax88796ProcessInterrupt(void)
457 {
458 unsigned char intr = ax88796Read(ISR);
459  
460 // check for receive overflow
461 if( intr & OVW )
462 ax88796ReceiveOverflowRecover();
463 }
464  
465  
466 void ax88796ReceiveOverflowRecover(void)
467 {
468 // receive buffer overflow handling procedure
469 // as specified in the AX88796 datasheet
470  
471 unsigned char cmdReg;
472 unsigned char resend=0;
473  
474 // check if we were transmitting something
475 cmdReg = ax88796Read(CR);
476 // stop the interface
477 ax88796Write(CR, (RD2|STOP));
478 // wait for timeout
479 delay_ms(2);
480 // clear remote byte count registers
481 ax88796Write(RBCR0, 0x00);
482 ax88796Write(RBCR1, 0x00);
483  
484 // if we were transmitting something
485 if(cmdReg & TXP)
486 {
487 // check if the transmit completed
488 cmdReg = ax88796Read(ISR);
489 if((cmdReg & PTX) || (cmdReg & TXE))
490 resend = 0; // transmit completed
491 else
492 resend = 1; // transmit was interrupted, must resend
493 }
494 // switch to loopback mode
495 ax88796Write(TCR, LB0);
496 // start the interface
497 ax88796Write(CR, (RD2|START));
498 // set boundary
499 ax88796Write(BNRY, RXSTART_INIT);
500 // go to page 1
501 ax88796Write(CR, (PS0|RD2|START));
502 // set current page register
503 ax88796Write(CPR, RXSTART_INIT+1);
504 // go to page 0
505 ax88796Write(CR, (RD2|START));
506 // clear the overflow int
507 ax88796Write(ISR, OVW);
508 // switch to normal (non-loopback mode)
509 ax88796Write(TCR, TCR_INIT);
510  
511 // if previous transmit was interrupted, then resend
512 if(resend)
513 ax88796Write(CR, (RD2|TXP|START));
514  
515 // recovery completed
516 }
517  
518  
519 #define set_mdc ax88796Write(MEMR,ax88796Read(MEMR)|0x01);
520 #define clr_mdc ax88796Write(MEMR,ax88796Read(MEMR)&0xFE);
521  
522 #define mii_clk set_mdc; clr_mdc;
523  
524 #define set_mdir ax88796Write(MEMR,ax88796Read(MEMR)|0x02);
525 #define clr_mdir ax88796Write(MEMR,ax88796Read(MEMR)&0xFD);
526  
527 #define set_mdo ax88796Write(MEMR,ax88796Read(MEMR)|0x08)
528 #define clr_mdo ax88796Write(MEMR,ax88796Read(MEMR)&0xF7)
529  
530 #define mii_write clr_mdo; mii_clk; \
531 set_mdo; mii_clk; \
532 clr_mdo; mii_clk; \
533 set_mdo; mii_clk;
534  
535 #define mii_read clr_mdo; mii_clk; \
536 set_mdo; mii_clk; \
537 set_mdo; mii_clk; \
538 clr_mdo; mii_clk;
539  
540 #define mii_r_ta mii_clk; \
541  
542 #define mii_w_ta set_mdo; mii_clk; \
543 clr_mdo; mii_clk;
544  
545 void ax88796WriteMii(unsigned char phyad,unsigned char regad,unsigned int mii_data)
546 {
547 unsigned char mask8;
548 unsigned int i,mask16;
549  
550 mii_write;
551  
552 mask8 = 0x10;
553 for(i=0;i<5;++i)
554 {
555 if(mask8 & phyad)
556 set_mdo;
557 else
558 clr_mdo;
559 mii_clk;
560 mask8 >>= 1;
561 }
562 mask8 = 0x10;
563 for(i=0;i<5;++i)
564 {
565 if(mask8 & regad)
566 set_mdo;
567 else
568 clr_mdo;
569 mii_clk;
570 mask8 >>= 1;
571 }
572 mii_w_ta;
573  
574 mask16 = 0x8000;
575 for(i=0;i<16;++i)
576 {
577 if(mask16 & mii_data)
578 set_mdo;
579 else
580 clr_mdo;
581 mii_clk;
582 mask16 >>= 1;
583 }
584 }
585  
586 unsigned int ax88796ReadMii(unsigned char phyad,unsigned char regad)
587 {
588 unsigned char mask8,i;
589 unsigned int mask16,result16;
590  
591 mii_read;
592  
593 mask8 = 0x10;
594 for(i=0;i<5;++i)
595 {
596 if(mask8 & phyad)
597 set_mdo;
598 else
599 clr_mdo;
600 mii_clk;
601 mask8 >>= 1;
602 }
603 mask8 = 0x10;
604 for(i=0;i<5;++i)
605 {
606 if(mask8 & regad)
607 set_mdo;
608 else
609 clr_mdo;
610 mii_clk;
611 mask8 >>= 1;
612 }
613  
614 mii_r_ta;
615  
616 mask16 = 0x8000;
617 result16 = 0x0000;
618 for(i=0;i<16;++i)
619 {
620 mii_clk;
621 if(ax88796Read(MEMR) & 0x04)
622 {
623 result16 |= mask16;
624 }
625 else
626 {
627 asm volatile ("nop");
628 break;
629 }
630 mask16 >>= 1;
631 }
632 return result16;
633 }
634  
635  
636 void ax88796RegDump(void)
637 {
638 unsigned char result;
639 result = ax88796Read(TR);
640  
641 rprintf("Media State: ");
642 if(!(result & AUTOD))
643 rprintf("Autonegotiation\r\n");
644 else if(result & RST_B)
645 rprintf("PHY in Reset \r\n");
646 else if(!(result & RST_10B))
647 rprintf("10BASE-T \r\n");
648 else if(!(result & RST_TXB))
649 rprintf("100BASE-T \r\n");
650  
651 //rprintf("TR regsiter : %x\r\n",result);
652 //result = read_mii(0x10,0);
653 //rprintf("MII regsiter 0x10: %x\r\n",result);
654  
655 rprintfProgStrM("Page0: CR BNRY PSR PST ISR TSR RSR MMR TR GPI\r\n");
656 rprintfProgStrM(" ");
657 rprintfu08(ax88796Read(CR));
658 rprintfProgStrM(" ");
659 rprintfu08(ax88796Read(BNRY));
660 rprintfProgStrM(" ");
661 rprintfu08(ax88796Read(PSTART));
662 rprintfProgStrM(" ");
663 rprintfu08(ax88796Read(PSTOP));
664 rprintfProgStrM(" ");
665 rprintfu08(ax88796Read(ISR));
666 rprintfProgStrM(" ");
667 rprintfu08(ax88796Read(TSR));
668 rprintfProgStrM(" ");
669 rprintfu08(ax88796Read(RSR));
670 rprintfProgStrM(" ");
671 rprintfu08(ax88796Read(MEMR));
672 rprintfProgStrM(" ");
673 rprintfu08(ax88796Read(TR));
674 rprintfProgStrM(" ");
675 rprintfu08(ax88796Read(GPI));
676 rprintfCRLF();
677  
678 ax88796Write(CR,ax88796Read(CR)|PS0);
679  
680 rprintf("Page1: CR PAR CPR\r\n");
681 rprintfProgStrM(" ");
682 rprintfu08(ax88796Read(CR));
683 rprintfProgStrM(" ");
684 rprintfChar(ax88796Read(PAR0));
685 rprintfChar(ax88796Read(PAR1));
686 rprintfChar(ax88796Read(PAR2));
687 rprintfChar(ax88796Read(PAR3));
688 rprintfChar(ax88796Read(PAR4));
689 rprintfChar(ax88796Read(PAR5));
690 rprintfProgStrM(" ");
691 rprintfu08(ax88796Read(CPR));
692  
693 ax88796Write(CR,ax88796Read(CR)&~PS0);
694  
695 delay_ms(25);
696 }
697  
698 /*
699 unsigned char ax88796ReceiveEmpty(void)
700 {
701 unsigned char temp;
702  
703 // read CPR from page 1
704 ax88796Write(CR,0x62);
705 temp = ax88796Read(CPR);
706  
707 // return to page 0
708 ax88796Write(CR,0x22);
709  
710 return ( ax88796Read(BNRY) == temp );
711  
712 }*/
713  
714  
715  
716  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3