BOOTLOADER
Main Page
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
bootloader
external drivers
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
24
INT32U
uiTemp
;
25
INT16U
usiTemp
;
26
INT8U
ucTemp
;
27
DM9000_CONTROL
Dm9000Ctrl
;
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
);
39
BOOL
F_Dm9000InUseCheck
(
void
);
40
BOOL
F_Dm9000Allocate
(
INT16U
UserId);
41
BOOL
F_Dm9000Release
(
INT16U
UserId);
42
BOOL
F_Dm9000InitialStart
(
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);
48
INT8U
F_Dm9000InitialPassCheck
(
void
);
49
BOOL
F_Dm9000PacketTransmit
(
INT8U
*pPacketData,
INT16U
PacketLength);
50
INT32U
F_Dm9000PacketReceive
(
INT8U
*pPacketData,
INT32U
PacketLength);
51
BOOL
F_Dm9000PacketReceiveCheck
(
void
);
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
88
F_Dm9000IoWrite
(
DM9000_NSR
,(
NSR_WAKEST
|
NSR_TX2END
|
NSR_TX1END
));
// clear tx status
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++){
97
if
(
F_Dm9000PhyRead
(
DM9000_PHY_STATUS
)&
BIT_AUTO_N_COMPL
)
break
;
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
}
160
INT8U
F_Dm9000ReadyCheck
(
void
){
161
if
(Dm9000Ctrl.
State
==
Dm9000IdleState
)
return
TRUE
;
162
else
return
FALSE
;
163
}
164
INT8U
F_Dm9000InUseCheck
(
void
){
165
if
(Dm9000Ctrl.
InUse
==
TRUE
)
return
TRUE
;
166
else
return
FALSE
;
167
}
168
INT8U
F_Dm9000Allocate
(
INT16U
UserId){
169
if
(Dm9000Ctrl.
InUse
==
FALSE
){
170
Dm9000Ctrl.
InUse
=
TRUE
;
171
Dm9000Ctrl.
UserId
=UserId;
172
return
TRUE
;
173
}
174
else
return
FALSE
;
175
}
176
INT8U
F_Dm9000Release
(
INT16U
UserId){
177
if
((Dm9000Ctrl.
InUse
==
TRUE
)&&(Dm9000Ctrl.
UserId
==UserId)){
178
Dm9000Ctrl.
InUse
=
FALSE
;
179
return
TRUE
;
180
}
181
else
return
FALSE
;
182
}
183
INT8U
F_Dm9000InitialStart
(
INT16U
UserId){
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
198
F_Dm9000IoWrite
(
DM9000_NCR
,3);
199
for
(i=0;i<8000;i++);
// delay 20us
200
F_Dm9000IoWrite
(
DM9000_NCR
,3);
201
for
(i=0;i<40000;i++);
// delay 1ms
202
}
203
BOOL
F_Dm9000Probe
(
void
){
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
}
217
void
F_Dm9000ModeSet
(
INT8U
Mode){
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
}
242
INT8U
F_Dm9000MacAddressSet
(
INT16U
UserId,
INT8U
*pMacAddress){
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
}
254
INT8U
F_Dm9000IpAddressSet
(
INT16U
UserId,
INT8U
*pIpAddress){
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
}
264
INT8U
F_Dm9000InitialPassCheck
(
void
){
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
281
while
(
F_Dm9000IoRead
(
DM9000_TCR
)&
TCR_TXREQ
){
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
315
F_Dm9000ByteWrite
(
DM9000_MRCMD
,
DM9000_INDEX
);
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
}
330
BOOL
F_Dm9000PacketReceiveCheck
(
void
){
331
INT8U
RxByte;
332
333
F_Dm9000IoRead
(
DM9000_MRCMDX
);
// ready status register w/o data pointer progress
334
F_Dm9000IoRead
(
DM9000_MRRH
);
335
F_Dm9000IoRead
(
DM9000_MRRL
);
336
RxByte=
F_Dm9000IoRead
(
DM9000_MRCMDX
);
337
if
(RxByte==0)
return
FALSE
;
// no rx data
338
else
if
(RxByte==0x01)
return
TRUE
;
339
else
{
340
F_Dm9000IoWrite
(
DM9000_RCR
,0x00);
341
F_Dm9000IoWrite
(
DM9000_ISR
,0x80);
342
F_Dm9000Reset
();
343
return
FALSE
;
344
}
345
}
346
INT8U
F_Dm9000IoRead
(
INT8U
Address){
347
F_Dm9000ByteWrite
(Address,
DM9000_INDEX
);
348
return
F_Dm9000ByteRead
(
DM9000_DATA
);
349
}
350
void
F_Dm9000IoWrite
(
INT8U
Address,
INT8U
Data){
351
F_Dm9000ByteWrite
(Address,
DM9000_INDEX
);
352
F_Dm9000ByteWrite
(Data,
DM9000_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
Generated on Wed Jun 13 2012 00:03:09 for BOOTLOADER by
1.8.1.1