BOOTLOADER
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
dm9000a.c
Go to the documentation of this file.
1 /******************************************************
2 * Function: dm9000a ethernet controler driver
3 *
4 * File: dm9000a.c
5 * Author: Book Chen
6 * Date: 2008.07.18
7 *******************************************************
8 */
9 #include "includes.h"
10 
11 #if(DEBUG_DM9000A==1)
12  #define DEBUG_DM9000A_INFO 1
13 #else
14  #define DEBUG_DM9000A_INFO 0
15 #endif
16 
17 #define Dm9000IdleState 0
18 #define Dm9000InitialState0 1
19 #define Dm9000InitialState1 2
20 #define Dm9000InitialState2 3
21 #define Dm9000InitialState3 4
22 #define Dm9000InitialState4 5
23 
28 
29 #define F_Dm9000ByteWrite(d,r) (*(volatile INT8U *)r=d)
30 #define F_Dm9000WordWrite(d,r) (*(volatile INT16U *)r=d)
31 #define F_Dm9000LongWrite(d,r) (*(volatile INT32U *)r=d)
32 #define F_Dm9000ByteRead(r) (*(volatile INT8U *)r)
33 #define F_Dm9000WordRead(r) (*(volatile INT16U *)r)
34 #define F_Dm9000LongRead(r) (*(volatile INT32U *)r)
35 
36 void F_Dm9000Init(void);
37 void F_Dm9000Svc(void);
38 INT8U F_Dm9000Check(void);
41 BOOL F_Dm9000Release(INT16U UserId);
43 void F_Dm9000Reset(void);
44 BOOL F_Dm9000Probe(void);
45 void F_Dm9000ModeSet(INT8U Mode);
46 BOOL F_Dm9000MacAddressSet(INT16U UserId,INT8U *pMacAddress);
47 BOOL F_Dm9000IpAddressSet(INT16U UserId,INT8U *pIpAddress);
49 BOOL F_Dm9000PacketTransmit(INT8U *pPacketData,INT16U PacketLength);
50 INT32U F_Dm9000PacketReceive(INT8U *pPacketData,INT32U PacketLength);
52 INT8U F_Dm9000IoRead(INT8U Address);
53 void F_Dm9000IoWrite(INT8U Address,INT8U Data);
54 INT16U F_Dm9000PhyRead(INT8U RegisterAddr);
55 void F_Dm9000PhyWrite(INT8U RegisterAddr,INT16U Value);
56 
57 void F_Dm9000Init(void){
58  Dm9000Ctrl.InitialPass=FALSE;
59  Dm9000Ctrl.IoBase=DM9000_ADDRESS;
60  Dm9000Ctrl.MemBase=0;
61  Dm9000Ctrl.LinkType=DM9000_LINK_UNKNOW;
62  Dm9000Ctrl.Id=ID_DM9000;
63  Dm9000Ctrl.InUse=FALSE;
64  Dm9000Ctrl.State=Dm9000IdleState;
65  Dm9000Ctrl.Timer=0;
66 }
67 void F_Dm9000Svc(void){
68  INT16U i,j;
69  INT16U PhyRegValue;
70 
71  switch(Dm9000Ctrl.State){
72  case Dm9000IdleState:
73  break;
74  case Dm9000InitialState0:
75  F_Dm9000Reset();
76  if(F_Dm9000Probe()==FALSE){
77  #if(DEBUG_DM9000A_INFO==1)
78  printf("\n device pid vid fail ");
79  #endif
80  Dm9000Ctrl.State=Dm9000IdleState;
81  break;
82  }
83  F_Dm9000ModeSet(DM9000_AUTO); // set phy operation mode
84  F_Dm9000IoWrite(DM9000_NCR,0x0); // only intern phy supported by now
85  F_Dm9000IoWrite(DM9000_TCR,0); // tx polling clear
86  F_Dm9000IoWrite(DM9000_BPTR,0x3f); // Less 3Kb, 200us
87  F_Dm9000IoWrite(DM9000_SMCR,0); // special mode
89  F_Dm9000IoWrite(DM9000_ISR,0x0f); // clear interrupt status
90  i=DM9000_PAR;
91  for(j=0;j<6;j++) F_Dm9000IoWrite(i++,Dm9000Ctrl.MacAddress[j]);
92  i=DM9000_MAR;
93  for(j=0;j<8;j++) F_Dm9000IoWrite(i++,0xff);
94  F_Dm9000IoWrite(DM9000_RCR,(RCR_DIS_LONG|RCR_DIS_CRC|RCR_RXEN)); // rx enable...discard long packet,crc packet
95  F_Dm9000IoWrite(DM9000_IMR,0xa3); // enable interrupt of link status,rx,and tx
96  for(i=0;i<1000;i++){
98  //break;
99  }
100  //Dm9000Ctrl.State=Dm9000IdleState;
101  //break;
102  if(i>=1000){
103  Dm9000Ctrl.State=Dm9000IdleState;
104  Dm9000Ctrl.Status=FALSE;
105  #if(DEBUG_DM9000A_INFO==1)
106  printf("\n phy status fail ");
107  #endif
108  break;
109  }
110  PhyRegValue=F_Dm9000PhyRead(DM9000_PHY_SCS)>>12;
111  switch(PhyRegValue){
112  case 1:
113  Dm9000Ctrl.LinkType=DM9000_LINK_10HDX;
114  #if(DEBUG_DM9000A_INFO==1)
115  printf("\n operating at DM9000_LINK_10HDX ");
116  #endif
117  break;
118  case 2:
119  Dm9000Ctrl.LinkType=DM9000_LINK_10FDX;
120  #if(DEBUG_DM9000A_INFO==1)
121  printf("\n operating at DM9000_LINK_10FDX ");
122  #endif
123  break;
124  case 4:
125  Dm9000Ctrl.LinkType=DM9000_LINK_100HDX;
126  #if(DEBUG_DM9000A_INFO==1)
127  printf("\n operating at DM9000_LINK_100HDX ");
128  #endif
129  break;
130  case 8:
131  Dm9000Ctrl.LinkType=DM9000_LINK_100FDX;
132  #if(DEBUG_DM9000A_INFO==1)
133  printf("\n operating at DM9000_LINK_100FDX ");
134  #endif
135  break;
136  default:
137  Dm9000Ctrl.LinkType=DM9000_LINK_UNKNOW;
138  #if(DEBUG_DM9000A_INFO==1)
139  printf("\n operating at DM9000_LINK_UNKNOW %4x ",PhyRegValue);
140  #endif
141  break;
142  }
143  Dm9000Ctrl.State=Dm9000InitialState1;
144  break;
145  case Dm9000InitialState1:
146  Dm9000Ctrl.State=Dm9000InitialState2;
147  break;
148  case Dm9000InitialState2:
149  Dm9000Ctrl.State=Dm9000InitialState3;
150  break;
151  case Dm9000InitialState3:
152  Dm9000Ctrl.State=Dm9000InitialState4;
153  break;
154  case Dm9000InitialState4:
155  Dm9000Ctrl.InitialPass=TRUE;
156  Dm9000Ctrl.State=Dm9000IdleState;
157  break;
158  }
159 }
161  if(Dm9000Ctrl.State==Dm9000IdleState) return TRUE;
162  else return FALSE;
163 }
165  if(Dm9000Ctrl.InUse==TRUE) return TRUE;
166  else return FALSE;
167 }
169  if(Dm9000Ctrl.InUse==FALSE){
170  Dm9000Ctrl.InUse=TRUE;
171  Dm9000Ctrl.UserId=UserId;
172  return TRUE;
173  }
174  else return FALSE;
175 }
177  if((Dm9000Ctrl.InUse==TRUE)&&(Dm9000Ctrl.UserId==UserId)){
178  Dm9000Ctrl.InUse=FALSE;
179  return TRUE;
180  }
181  else return FALSE;
182 }
184  if((Dm9000Ctrl.InUse==TRUE)&&(Dm9000Ctrl.UserId==UserId)){
185  Dm9000Ctrl.State=Dm9000InitialState0;
186  return TRUE;
187  }
188  else return FALSE;
189 }
190 void F_Dm9000Reset(void){
191  INT32U i;
192 
193  // set the internal PHY power-on, GPIOs normal, and wait 2ms
194  F_Dm9000IoWrite(DM9000_GPR,1); // power-down phy
195  for(i=0;i<20000;i++); // cpu 400mhz...500us=400x500 (i guess)
196  F_Dm9000IoWrite(DM9000_GPR,0); // GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY
197  for(i=0;i<80000;i++); // wait 2ms for PHY power-on ready
199  for(i=0;i<8000;i++); // delay 20us
201  for(i=0;i<40000;i++); // delay 1ms
202 }
204  INT32U IdValue;
205 
206  IdValue=0;
207  IdValue|=F_Dm9000IoRead(DM9000_VIDL);
208  IdValue|=(F_Dm9000IoRead(DM9000_VIDH)&0xff)<<8;
209  IdValue|=(F_Dm9000IoRead(DM9000_PIDL)&0xff)<<16;
210  IdValue|=(F_Dm9000IoRead(DM9000_PIDH)&0xff)<<24;
211  #if(DEBUG_DM9000A_INFO==1)
212  //printf("\n DM9000A PIDVID: %8x ",IdValue);
213  #endif
214  if(IdValue==DM9000_ID) return TRUE;
215  else return FALSE;
216 }
218  switch(Mode){
219  default:
220  case DM9000_AUTO:
221  F_Dm9000PhyWrite(0,0x1200);
222  F_Dm9000PhyWrite(4,0x01e1);
223  break;
224  case DM9000_10MHD:
225  F_Dm9000PhyWrite(0,0x1000);
226  F_Dm9000PhyWrite(4,0x0021);
227  break;
228  case DM9000_10MFD:
229  F_Dm9000PhyWrite(0,0x1100);
230  F_Dm9000PhyWrite(4,0x0041);
231  break;
232  case DM9000_100MHD:
233  F_Dm9000PhyWrite(0,0x3000);
234  F_Dm9000PhyWrite(4,0x0081);
235  break;
236  case DM9000_100MFD:
237  F_Dm9000PhyWrite(0,0x3100);
238  F_Dm9000PhyWrite(4,0x0101);
239  break;
240  }
241 }
243  if((Dm9000Ctrl.InUse==TRUE)&&(Dm9000Ctrl.UserId==UserId)){
244  Dm9000Ctrl.MacAddress[0]=pMacAddress[0];
245  Dm9000Ctrl.MacAddress[1]=pMacAddress[1];
246  Dm9000Ctrl.MacAddress[2]=pMacAddress[2];
247  Dm9000Ctrl.MacAddress[3]=pMacAddress[3];
248  Dm9000Ctrl.MacAddress[4]=pMacAddress[4];
249  Dm9000Ctrl.MacAddress[5]=pMacAddress[5];
250  return TRUE;
251  }
252  else return FALSE;
253 }
255  if((Dm9000Ctrl.InUse==TRUE)&&(Dm9000Ctrl.UserId==UserId)){
256  Dm9000Ctrl.IpAddress[0]=pIpAddress[0];
257  Dm9000Ctrl.IpAddress[1]=pIpAddress[1];
258  Dm9000Ctrl.IpAddress[2]=pIpAddress[2];
259  Dm9000Ctrl.IpAddress[3]=pIpAddress[3];
260  return TRUE;
261  }
262  else return FALSE;
263 }
265  if(Dm9000Ctrl.InitialPass==TRUE) return TRUE;
266  else return FALSE;
267 }
268 BOOL F_Dm9000PacketTransmit(INT8U *pPacketData,INT16U PacketLength){
269  INT16U *pData;
270  INT16U TxLength;
271  INT16U i;
272 
273  F_Dm9000ByteWrite(DM9000_MWCMD,DM9000_INDEX); // set address index for data write
274  pData=(INT16U *)pPacketData;
275  TxLength=(PacketLength+1)/2;
276  for(i=0;i<TxLength;i++) F_Dm9000WordWrite(*pData++,DM9000_DATA); // data out
277  F_Dm9000IoWrite(DM9000_TXPLH,(PacketLength>>8)&0xff); // set tx length
278  F_Dm9000IoWrite(DM9000_TXPLL,PacketLength&0xff);
279  F_Dm9000IoWrite(DM9000_TCR, TCR_TXREQ); // tx request. this bit is auto cleared after tx done.
280  Dm9000Ctrl.Timer=500; // 0.5 sec
282  if(Dm9000Ctrl.Timer==0){
283  #if(DEBUG_DM9000A_INFO==1)
284  printf("dm9000 tx fail");
285  #endif
286  return FALSE; // time out
287  }
288  }
289  #if(DEBUG_DM9000A_INFO==1)
290  //printf("dm9000 tx ok");
291  #endif
292  return TRUE;
293 }
294 INT32U F_Dm9000PacketReceive(INT8U *pPacketData,INT32U PacketLength){
295  INT8U RxByte;
296  INT16U RxStatus,RxLength;
297  INT16U *pData;
298  INT16U i;
299 
300  // check packet data...using DM9000_MRCMD
301  F_Dm9000IoRead(DM9000_MRCMDX); // issue this register to start dm9000a prefetch sram data
302  F_Dm9000IoRead(DM9000_MRRH); // ?? important ??
303  F_Dm9000IoRead(DM9000_MRRL); // ?? important ??
304  RxByte=F_Dm9000IoRead(DM9000_MRCMDX); // use DM9000_MRCMDX, packet read index no increase
305  // packet 1,status,byte count low,byte count high
306  if(RxByte==0) return 0;
307  else if(RxByte==DM9000_PACKET_READY); // 1...see dm9000a spec. p42 packet reception
308  else if(RxByte>1){ // 1 only
309  F_Dm9000IoWrite(DM9000_RCR,0x00); // stop device
310  F_Dm9000IoWrite(DM9000_ISR,0x80); // stop int request
311  F_Dm9000Reset();
312  return 0;
313  }
314  // start to read packet...using DM9000_MRCMD
316  RxStatus=F_Dm9000WordRead(DM9000_DATA); // 01h + status byte
317  RxLength=F_Dm9000WordRead(DM9000_DATA); // byte count low + byte count high
318  if((RxStatus&0xbf00)||(RxLength<64)||(RxLength>PacketLength)){
319  if(RxStatus&0x0100); // rx fifo error
320  if(RxStatus&0x0200); // rx crc error
321  if(RxStatus&0x8000); // rx length error
322  if(RxLength>PacketLength) F_Dm9000Reset();
323  return 0; // reutrn length 0...no data
324  }
325  pData=(INT16U *)pPacketData;
326  PacketLength=(RxLength+1)/2;
327  for(i=0;i<PacketLength;i++) *pData++=F_Dm9000WordRead(DM9000_DATA);
328  return (INT32U)RxLength;
329 }
331  INT8U RxByte;
332 
333  F_Dm9000IoRead(DM9000_MRCMDX); // ready status register w/o data pointer progress
337  if(RxByte==0) return FALSE; // no rx data
338  else if(RxByte==0x01) return TRUE;
339  else {
342  F_Dm9000Reset();
343  return FALSE;
344  }
345 }
349 }
350 void F_Dm9000IoWrite(INT8U Address,INT8U Data){
353 }
354 INT16U F_Dm9000PhyRead(INT8U RegisterAddr){ // read phy registers
355  INT16U Value;
356  INT16U i;
357 
358  F_Dm9000IoWrite(DM9000_EPAR,DM9000_PHY|RegisterAddr); // set phy status register addr in EPAR reg.
359  F_Dm9000IoWrite(DM9000_EPCR,0x0c); // 0x0c=0x08+0x04...0x08 select phy,0x04 read command
360  for(i=0;i<4000;i++); // wait read command complete
361  F_Dm9000IoWrite(DM9000_EPCR,0x0); // Clear phyxcer read command ??
362  Value=((F_Dm9000IoRead(DM9000_EPDRH)&0xff)<<8)|(F_Dm9000IoRead(DM9000_EPDRL)&0xff);
363  return Value;
364 }
365 void F_Dm9000PhyWrite(INT8U RegisterAddr,INT16U Value){ // write phy registers
366  INT16U i;
367 
368  F_Dm9000IoWrite(DM9000_EPAR,DM9000_PHY|RegisterAddr); // Fill the phyxcer register into REG_0C
369  F_Dm9000IoWrite(DM9000_EPDRL,(Value&0xff)); // Fill the written data into REG_0D & REG_0E
370  F_Dm9000IoWrite(DM9000_EPDRH,((Value>>8)&0xff));
371  F_Dm9000IoWrite(DM9000_EPCR,0xa); // 0x0a=0x08+0x02...0x08 select phy,0x02 write command
372  for(i=0;i<60000;i++); // Wait write command complete
373  F_Dm9000IoWrite(DM9000_EPCR,0x0); // Clear phyxcer write command
374 }
375 
376 
377