BOOTLOADER
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
cs8900.c
Go to the documentation of this file.
1 //==========
2 // Project name: MyArm920t
3 // Author: Book Chen
4 // Start time: 2007.06.04
5 // Function: Driver of ethernet controller CS8900
6 //==========
7 #include "includes.h"
8 
9 #define Cs8900IdleState 0
10 #define Cs8900InitialState0 1
11 #define Cs8900InitialState1 2
12 #define Cs8900InitialState2 3
13 #define Cs8900InitialState3 4
14 #define Cs8900InitialState4 5
15 
16 #define MAX_COUNT 0x00100000
17 
19 
20 #define F_Cs8900IoRead(Offset) ((INT16U)*((volatile INT16U*)(Cs8900Ctrl.IoBase+(Offset))))
21 #define F_Cs8900IoWrite(Offset,Data) *((volatile INT16U*)(Cs8900Ctrl.IoBase+(Offset)))=(INT16U)(Data)
22 #define F_Cs8900MemryRead(Offset) ((INT16U)*((volatile INT16U*)(Cs8900Ctrl.MemBase+(Offset))))
23 #define F_Cs8900MemoryWrite(Offset,Data) *((volatile INT16U*)(Cs8900Ctrl.MemBase+(Offset)))=(INT16U)(Data)
24 #define CS8900_MEMORY_MODE 0
25 #if(CS8900_MEMORY_MODE==1)
26  #define F_Cs8900RegisterRead1 F_Cs8900RegisterRead
27  #define F_Cs8900RegisterRead2 F_Cs8900MemryRead
28  #define F_Cs8900RegisterWrite1 F_Cs8900RegisterWrite
29  #define F_Cs8900RegisterWrite2 F_Cs8900MemoryWrite
30 #else
31  #define F_Cs8900RegisterRead1 F_Cs8900RegisterRead
32  #define F_Cs8900RegisterRead2 F_Cs8900RegisterRead
33  #define F_Cs8900RegisterWrite1 F_Cs8900RegisterWrite
34  #define F_Cs8900RegisterWrite2 F_Cs8900RegisterWrite
35 #endif
36 void F_Cs8900Init(void);
37 void F_Cs8900Svc(void);
42 INT8U F_Cs8900MacAddressSet(INT16U UserId,INT8U *pMacAddress);
43 INT8U F_Cs8900IpAddressSet(INT16U UserId,INT8U *pIpAddress);
46 void F_Cs8900RegisterWrite(INT16U Offset,INT16U Data);
47 void F_Cs8900IrqEnable(void);
48 INT32U F_Cs8900PacketReceive(INT8U *pPacketData,INT32U PacketLength);
49 INT8U F_Cs8900PacketTransmit(INT8U *pPacketData,INT16U PacketLength);
51 INT8U F_Cs8900Link(void);
52 
53 void F_Cs8900Init(void){
54  Cs8900Ctrl.InitialPass=FALSE;
55  Cs8900Ctrl.IoBase=CS8900_ADDRESS;
56  Cs8900Ctrl.MemBase=0;
57  Cs8900Ctrl.Id=ID_CS8900;
58  Cs8900Ctrl.InUse=FALSE;
59  Cs8900Ctrl.State=Cs8900IdleState;
60 }
61 void F_Cs8900Svc(void){
62  INT16U i;
63  INT16U *pMac;
64 
65  switch(Cs8900Ctrl.State){
66  case Cs8900IdleState:
67  break;
69  Cs8900Ctrl.InitialPass=FALSE;
70  // SPEC. 3.3.3 bus reset consideration
71  // IO_PACKET_PAGE_POINTER has sigunature 3000h.
73  #if(DEBUG_CS8900==1)
74  printf("\n sigunature %8x",i);
75  #endif
76  if((i&CS8900_SIGNATURE_MASK)!=CS8900_SIGNATURE_MASK){
77  #if(DEBUG_CS8900==1)
78  printf("\n sigunature error");
79  #endif
80  Cs8900Ctrl.State=Cs8900IdleState;
81  return;
82  }
83  // SPEC. 4.3.1 bus interface register EISA number
84  // EISA NUMBER 0x630E
86  #if(DEBUG_CS8900==1)
87  printf("\n EISA number %8x",i);
88  #endif
89  if(i!=CS8900_EISA_NUMBER){
90  #if(DEBUG_CS8900==1)
91  printf("\n EISA number error");
92  #endif
93  Cs8900Ctrl.State=Cs8900IdleState;
94  return;
95  }
96  // SPEC. 4.3.1 bus interface register ID code's 0s
98  #if(DEBUG_CS8900==1)
99  printf("\n CS8900_PRDCT_ID %8x",i);
100  #endif
102  #if(DEBUG_CS8900==1)
103  printf("\n product ID error");
104  #endif
105  Cs8900Ctrl.State=Cs8900IdleState;
106  return;
107  }
109  #if(DEBUG_CS8900==1)
110  printf("\n PKTPG_IO_BASE_ADDR %8x",i);
111  printf("\n CS8900 detected");
112  #endif
114  Cs8900Ctrl.State=Cs8900InitialState1;
115  break;
116  case Cs8900InitialState1:
117  if((F_Cs8900RegisterRead1(PKTPG_SELF_ST)&SELF_ST_INITD)==0) return; // wait cs8900 goes ready
118  #if(DEBUG_CS8900==1)
119  printf("\n initial ok ");
120  #endif
121  Cs8900Ctrl.State=Cs8900InitialState2;
122  break;
123  case Cs8900InitialState2:
124  if((F_Cs8900RegisterRead1(PKTPG_SELF_ST)&SELF_ST_SIBUSY)!=0) return; // wait cs8900 goes ready
125  #if(DEBUG_CS8900==1)
126  printf("\n initial done ");
127  #endif
128  Cs8900Ctrl.State=Cs8900InitialState3;
129  break;
130  case Cs8900InitialState3:
131  // set 10 base T and mode back off
134  // set frame receive interrupt enable
136  // set frame rx enable,
137  // set destination address match enable
138  // set broadcast address match enable
140  // {0x00,0x80,0x48,0x12,0x34,0x56}
141  pMac=(INT16U *)Cs8900Ctrl.MacAddress;
142  #if(DEBUG_CS8900==1)
143  printf("\n pMAC %4x ",*pMac);
144  #endif
145  F_Cs8900RegisterWrite2(PKTPG_INDIVISUAL_ADDR+0,*pMac++); // 158,159
146  #if(DEBUG_CS8900==1)
147  printf("\n pMAC %4x ",*pMac);
148  #endif
149  F_Cs8900RegisterWrite2(PKTPG_INDIVISUAL_ADDR+2,*pMac++); // 15a,15b
150  #if(DEBUG_CS8900==1)
151  printf("\n pMAC %4x ",*pMac);
152  #endif
153  F_Cs8900RegisterWrite2(PKTPG_INDIVISUAL_ADDR+4,*pMac ); // 15c,15d
154  // disable interrupts for frame tx
156  Cs8900Ctrl.State=Cs8900InitialState4;
157  break;
158  case Cs8900InitialState4:
159  // disable intrq 0,1,2,3 ...like interrupts(et0,et1,es0,ex0,ex1) in 8051
161  // enable interrupt generation...like "ea" in 8051
164  // enable packet rx,tx
167 
168  printf("\n CS8900 MAC initial ok");
169  Cs8900Ctrl.InitialPass=TRUE;
170  Cs8900Ctrl.State=Cs8900IdleState;
171  break;
172  }
173 }
175  if(Cs8900Ctrl.InUse==TRUE) return TRUE;
176  else return FALSE;
177 }
179  if(Cs8900Ctrl.InUse==FALSE){
180  Cs8900Ctrl.InUse=TRUE;
181  Cs8900Ctrl.UserId=UserId;
182  return TRUE;
183  }
184  else return FALSE;
185 }
187  if((Cs8900Ctrl.InUse==TRUE)&&(Cs8900Ctrl.UserId==UserId)){
188  Cs8900Ctrl.InUse=FALSE;
189  return TRUE;
190  }
191  else return FALSE;
192 }
194  if((Cs8900Ctrl.InUse==TRUE)&&(Cs8900Ctrl.UserId==UserId)){
195  Cs8900Ctrl.State=Cs8900InitialState0;
196  return TRUE;
197  }
198  else return FALSE;
199 }
201  if((Cs8900Ctrl.InUse==TRUE)&&(Cs8900Ctrl.UserId==UserId)){
202  Cs8900Ctrl.MacAddress[0]=pMacAddress[0];
203  Cs8900Ctrl.MacAddress[1]=pMacAddress[1];
204  Cs8900Ctrl.MacAddress[2]=pMacAddress[2];
205  Cs8900Ctrl.MacAddress[3]=pMacAddress[3];
206  Cs8900Ctrl.MacAddress[4]=pMacAddress[4];
207  Cs8900Ctrl.MacAddress[5]=pMacAddress[5];
208  return TRUE;
209  }
210  else return FALSE;
211 }
213  if((Cs8900Ctrl.InUse==TRUE)&&(Cs8900Ctrl.UserId==UserId)){
214  Cs8900Ctrl.IpAddress[0]=pIpAddress[0];
215  Cs8900Ctrl.IpAddress[1]=pIpAddress[1];
216  Cs8900Ctrl.IpAddress[2]=pIpAddress[2];
217  Cs8900Ctrl.IpAddress[3]=pIpAddress[3];
218  return TRUE;
219  }
220  else return FALSE;
221 }
223  if(Cs8900Ctrl.InitialPass==TRUE) return TRUE;
224  else return FALSE;
225 }
227  if(Cs8900Ctrl.State==Cs8900IdleState) return TRUE;
228  else return FALSE;
229 }
231  return F_Cs8900IoRead(Offset);
232 }
236 }
240 }
241 void F_Cs8900IrqEnable(void){
242  INT16U i;
243 
244  // disable intrq 0,1,2,3 ...like interrupts(et0,et1,es0,ex0,ex1) in 8051
246  // enable interrupt generation...like "ea" in 8051
249  // enable packet rx,tx
252 }
253 INT32U F_Cs8900PacketReceive(INT8U *pPacketData,INT32U PacketLength){
254  INT32U Length;
255  INT32U ReceiveLength=0;
256  INT16U *pData;
257  INT16U Data;
258 
259  Data=F_Cs8900IoRead(IO_RX_TX_DATA_0); // ignore first byte??
260  Length=F_Cs8900IoRead(IO_RX_TX_DATA_0); // read frame length
261  if(Length>PacketLength) Length=0; // frame length to large
262  pData=(INT16U *)pPacketData; // convert INT8U pointer to INT16U pointer
263  ReceiveLength=Length;
264  while(ReceiveLength!=0){
265  Data=F_Cs8900IoRead(IO_RX_TX_DATA_0); // host read frame data stored in cs8900 (in 16bits)
266  if(ReceiveLength==1){
267  *((INT8U*)pData)=(INT8U)Data; // last byte if odd frame length
268  ReceiveLength=0;
269  }
270  else{
271  *pData++=Data; // 16 bit
272  ReceiveLength-=2; // 2*8bit
273  }
274  }
275  return Length;
276 }
277 INT8U F_Cs8900PacketTransmit(INT8U *pPacketData,INT16U PacketLength){
278  INT16U *pData;
279  INT16U BusStatus;
280  INT32U i;
281 
282  // SPEC. 4.5.1
283  // set start transmission after entire frame is in cs8900
285  // SPEC. 4.5.2
286  // set tansmission packet length(in bytes)
287  F_Cs8900IoWrite(IO_TX_LENGTH,PacketLength);
288  for(i=0;i<MAX_COUNT;i++){ // polling time counter
289  BusStatus=F_Cs8900RegisterRead2(PKTPG_BUS_ST); // polling cs8900 ready
290  if(BusStatus&BUS_ST_RDY_4_TX_NOW) break; // polling status ready
291  }
292  if(i>=MAX_COUNT) return FALSE; // polling time out, return
293  pData=(INT16U *)pPacketData; // convert INT8U pointer to INT16U pointer
294  while(PacketLength!=0){
295  F_Cs8900IoWrite(IO_RX_TX_DATA_0, *pData++); // transmit data from host to cs8900(in 16bits)
296  if(PacketLength==1) PacketLength=0; // last byte if odd frame length
297  else PacketLength-=2;
298  }
299  return TRUE;
300 }
302  INT16U Event;
303 
304  // read INT_STATUS_QUEUE
305  // then check if REG_NUM_RX_EVENT is in
306  // then check if RX_EVENT_RX_OK is ok
307  // then check if RX_EVENT_IND_ADDR or RX_CTL_BROADCAST_A
308  // then return TRUE <-- there is a packet received
310  if(((Event&ISQ_REG_NUM)==REG_NUM_RX_EVENT)&& // check 000100
311  ((Event&RX_EVENT_RX_OK)==RX_EVENT_RX_OK)&& // has rx a frame
312  ((Event&RX_EVENT_IND_ADDR)|(Event&RX_CTL_BROADCAST_A))){
313  Cs8900Ctrl.RxEvent=Event;
314  //if(Event&RX_EVENT_IND_ADDR) Cs8900Ctrl.IsIndividual=TRUE;
315  //else Cs8900Ctrl.IsIndividual=FALSE;
316  //if(Event&RX_CTL_BROADCAST_A) Cs8900Ctrl.IsBroadcast=TRUE;
317  //else Cs8900Ctrl.IsBroadcast=FALSE;
318  return TRUE;
319  }
320  else return FALSE;
321 }
323  return TRUE;
324 }