📄 if_dm9000.c
字号:
//==========================================================================
2 //
3 // if_dm9000.c
4 //
5 // Davicom DM9000 ethernet driver
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2003, 2004 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //#####DESCRIPTIONBEGIN####
41 //
42 // Author(s): msalter
43 // Contributors: msalter
44 // Date: 2004-03-18
45 // Purpose:
46 // Description: hardware driver for Davicom DM9000 NIC
47 // Notes:
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52
53 #include <pkgconf/system.h>
54 #include <pkgconf/io_eth_drivers.h>
55 #include <pkgconf/devs_eth_davicom_dm9000.h>
56 #include <cyg/infra/cyg_type.h>
57 #include <cyg/infra/cyg_ass.h>
58 #include <cyg/hal/hal_arch.h>
59 #include <cyg/hal/hal_cache.h>
60 #include <cyg/hal/hal_intr.h>
61 #include <cyg/hal/hal_endian.h>
62 #include <cyg/infra/diag.h>
63 #include <cyg/hal/hal_if.h>
64 #include <cyg/hal/drv_api.h>
65 #include <cyg/io/eth/netdev.h>
66 #include <cyg/io/eth/eth_drv.h>
67
68 #include <dm9000_info.h>
69
70 #ifdef CYGPKG_REDBOOT
71 #include <pkgconf/redboot.h>
72 #include <redboot.h>
73 #include <flash_config.h>
74 #endif
75
76 #include CYGDAT_DEVS_ETH_DAVICOM_DM9000_INL
77
78 #define DM9000_PKT_MAX 1536
79
80 //
81 // Control and Status register offsets
82 //
83 #define DM_NCR 0x00
84 #define DM_NSR 0x01
85 #define DM_TCR 0x02
86 #define DM_TSRI 0x03
87 #define DM_TSRII 0x04
88 #define DM_RCR 0x05
89 #define DM_RSR 0x06
90 #define DM_ROCR 0x07
91 #define DM_BPTR 0x08
92 #define DM_FCTR 0x09
93 #define DM_FCR 0x0a
94 #define DM_EPCR 0x0b
95 #define DM_EPAR 0x0c
96 #define DM_EPDRL 0x0d
97 #define DM_EPDRH 0x0e
98 #define DM_WCR 0x0f
99 #define DM_PAR 0x10
100 #define DM_MAR 0x16
101 #define DM_GPCR 0x1e
102 #define DM_GPR 0x1f
103 #define DM_TRPAL 0x22
104 #define DM_TRPAH 0x23
105 #define DM_RWPAL 0x24
106 #define DM_RWPAH 0x25
107 #define DM_VIDL 0x28
108 #define DM_VIDH 0x29
109 #define DM_PIDL 0x2a
110 #define DM_PIDH 0x2b
111 #define DM_CHIPR 0x2c
112 #define DM_SMCR 0x2f
113 #define DM_MRCMDX 0xf0
114 #define DM_MRCMD 0xf2
115 #define DM_MDRAL 0xf4
116 #define DM_MDRAH 0xf5
117 #define DM_MWCMDX 0xf6
118 #define DM_MWCMD 0xf8
119 #define DM_MDWAL 0xfa
120 #define DM_MDWAH 0xfb
121 #define DM_TXPLL 0xfc
122 #define DM_TXPLH 0xfd
123 #define DM_ISR 0xfe
124 #define DM_IMR 0xff
125
126 // NCR (Network Control Register)
127 #define NCR_EXT_PHY (1 << 7) // 1 ==> external PHY, 0 ==> internal
128 #define NCR_WAKEEN (1 << 6) // enable wakeup events
129 #define NCR_FCOL (1 << 4) // force collision mode (test)
130 #define NCR_FDX (1 << 3) // full duplex (read-only for internal phy)
131 #define NCR_LBK_NOR (0 << 1) // loopback off
132 #define NCR_LBK_MAC (1 << 1) // MAC loopback
133 #define NCR_LBK_PHY (2 << 1) // PHY loopback
134 #define NCR_RST (1 << 0) // Reset (auto-clears after 10us)
135
136 // NSR (Network Status Register)
137 #define NSR_SPEED (1 << 7) // 0 = 100Mbps, 1 = 10Mbps
138 #define NSR_LINKST (1 << 6) // link status (1 = okay)
139 #define NSR_WAKEST (1 << 5) // wake status (clear by read)
140 #define NSR_TX2END (1 << 3) // TX packet 2 complete
141 #define NSR_TX1END (1 << 2) // TX packet 1 complete
142 #define NSR_RXOV (1 << 1) // RX overflow
143
144 // TCR (TX Control Register)
145 #define TCR_TJDIS (1 << 6) // TX jabber disable
146 #define TCR_EXCECM (1 << 5) // 0 = abort after 15 collisions
147 #define TCR_PAD_DIS2 (1 << 4)
148 #define TCR_CRC_DIS2 (1 << 3)
149 #define TCR_PAD_DIS1 (1 << 2)
150 #define TCR_CRC_DIS1 (1 << 1)
151 #define TCR_TXREQ (1 << 0)
152
153 // TSR (TX Status Register)
154 #define TSR_TJTO (1 << 7)
155 #define TSR_LC (1 << 6)
156 #define TSR_NC (1 << 5)
157 #define TSR_LCOL (1 << 4)
158 #define TSR_COL (1 << 3)
159 #define TSR_EC (1 << 2)
160
161 // RCR (RX Control Register)
162 #define RCR_WTDIS (1 << 6)
163 #define RCR_DIS_LONG (1 << 5)
164 #define RCR_DIS_CRC (1 << 4)
165 #define RCR_ALL (1 << 3)
166 #define RCR_RUNT (1 << 2)
167 #define RCR_PRMSC (1 << 1)
168 #define RCR_RXEN (1 << 0)
169
170 // RSR (RX Status Register)
171 #define RSR_RF (1 << 7)
172 #define RSR_MF (1 << 6)
173 #define RSR_LCS (1 << 5)
174 #define RSR_RWTO (1 << 4)
175 #define RSR_PLE (1 << 3)
176 #define RSR_AE (1 << 2)
177 #define RSR_CE (1 << 1)
178 #define RSR_FOE (1 << 0)
179
180 // FCR (Flow Control Register)
181 #define FCR_TXPO (1 << 7)
182 #define FCR_TXPF (1 << 6)
183 #define FCR_TXPEN (1 << 5)
184 #define FCR_BKPA (1 << 4)
185 #define FCR_BKPM (1 << 3)
186 #define FCR_RXPS (1 << 2)
187 #define FCR_RXPCS (1 << 1)
188 #define FCR_FLCE (1 << 0)
189
190 // EPCR (EEPROM & PHY Control Register)
191 #define EPCR_REEP (1 << 5)
192 #define EPCR_WEP (1 << 4)
193 #define EPCR_EPOS (1 << 3)
194 #define EPCR_ERPRR (1 << 2)
195 #define EPCR_ERPRW (1 << 1)
196 #define EPCR_ERRE (1 << 0)
197
198 // WCR (Wakeup Control Register)
199 #define WCR_LINKEN (1 << 5)
200 #define WCR_SAMPLEEN (1 << 4)
201 #define WCR_MAGICEN (1 << 3)
202 #define WCR_LINKST (1 << 2)
203 #define WCR_SAMPLEST (1 << 1)
204 #define WCR_MAGIGST (1 << 0)
205
206 // SMCR (Special Mode Control Register)
207 #define SMCR_SM_EN (1 << 7)
208 #define SMCR_FLC (1 << 2)
209 #define SMCR_FB1 (1 << 1)
210 #define SMCR_FB0 (1 << 0)
211
212 // ISR (Interrupt Status Register)
213 #define ISR_IOMODE_16 (0 << 6)
214 #define ISR_IOMODE_32 (1 << 6)
215 #define ISR_IOMODE_8 (2 << 6)
216 #define ISR_ROOS (1 << 3)
217 #define ISR_ROS (1 << 2)
218 #define ISR_PTS (1 << 1)
219 #define ISR_PRS (1 << 0)
220
221 // IMR (Interrupt Mask Register)
222 #define IMR_PAR (1 << 7)
223 #define IMR_ROOM (1 << 3)
224 #define IMR_ROM (1 << 2)
225 #define IMR_PTM (1 << 1)
226 #define IMR_PRM (1 << 0)
227
228
229 // Read one datum from 8-bit bus
230 static int read_data_8(struct dm9000 *p, cyg_uint8 *dest)
231 {
232 HAL_READ_UINT8(p->io_data, *dest);
233 return 1;
234 }
235
236 // Read one datum from 16-bit bus
237 static int read_data_16(struct dm9000 *p, cyg_uint8 *dest)
238 {
239 cyg_uint16 val;
240
241 HAL_READ_UINT16(p->io_data, val);
242 memcpy(dest, &val, 2);
243 return 2;
244 }
245
246 // Read one datum from 32-bit bus
247 static int read_data_32(struct dm9000 *p, cyg_uint8 *dest)
248 {
249 cyg_uint32 val;
250
251 HAL_READ_UINT32(p->io_data, val);
252 memcpy(dest, &val, 4);
253 return 4;
254 }
255
256
257 // Write one datum to 8-bit bus
258 static int write_data_8(struct dm9000 *p, cyg_uint8 *src)
259 {
260 HAL_WRITE_UINT8(p->io_data, *src);
261 return 1;
262 }
263
264 // Write one datum to 16-bit bus
265 static int write_data_16(struct dm9000 *p, cyg_uint8 *src)
266 {
267 cyg_uint16 val;
268
269 memcpy(&val, src, 2);
270 HAL_WRITE_UINT16(p->io_data, val);
271 return 2;
272 }
273
274 // Write one datum to 32-bit bus
275 static int write_data_32(struct dm9000 *p, cyg_uint8 *src)
276 {
277 cyg_uint32 val;
278
279 memcpy(&val, src, 4);
280 HAL_WRITE_UINT32(p->io_data, val);
281 return 4;
282 }
283
284
285
286 // Return one byte from DM9000 register
287 static cyg_uint8 getreg(struct dm9000 *p, cyg_uint8 reg)
288 {
289 cyg_uint8 val;
290 HAL_WRITE_UINT8(p->io_addr, reg);
291 HAL_READ_UINT8(p->io_data, val);
292 return val;
293 }
294
295 // Write one byte to DM9000 register
296 static void putreg(struct dm9000 *p, cyg_uint8 reg, cyg_uint8 val)
297 {
298 HAL_WRITE_UINT8(p->io_addr, reg);
299 HAL_WRITE_UINT8(p->io_data, val);
300 }
301
302 // Read a word from EEPROM
303 static cyg_uint16 eeprom_read(struct dm9000 *p, int offset)
304 {
305 putreg(p, DM_EPAR, offset);
306 putreg(p, DM_EPCR, EPCR_ERPRR);
307 while (getreg(p, DM_EPCR) & EPCR_ERRE)
308 ;
309 CYGACC_CALL_IF_DELAY_US(200);
310 putreg(p, DM_EPCR, 0);
311 return getreg(p, DM_EPDRL) | (getreg(p, DM_EPDRH) << 8);
312 }
313
314 // Write a word to EEPROM
315 static void eeprom_write(struct dm9000 *p, int offset, cyg_uint16 val)
316 {
317 putreg(p, DM_EPAR, offset);
318 putreg(p, DM_EPDRH, val >> 8);
319 putreg(p, DM_EPDRL, val);
320 putreg(p, DM_EPCR, EPCR_WEP | EPCR_ERPRW);
321 while (getreg(p, DM_EPCR) & EPCR_ERRE)
322 ;
323 CYGACC_CALL_IF_DELAY_US(200);
324 putreg(p, DM_EPCR, 0);
325 }
326
327 // Reload info from EEPROM
328 static void eeprom_reload(struct dm9000 *p)
329 {
330 putreg(p, DM_EPCR, EPCR_REEP);
331 while (getreg(p, DM_EPCR) & EPCR_ERRE)
332 ;
333 CYGACC_CALL_IF_DELAY_US(200);
334 putreg(p, DM_EPCR, 0);
335 }
336
337
338 // Read a word from PHY
339 static cyg_uint16 phy_read(struct dm9000 *p, int offset)
340 {
341 putreg(p, DM_EPAR, 0x40 + offset);
342 putreg(p, DM_EPCR, EPCR_EPOS | EPCR_ERPRR);
343 CYGACC_CALL_IF_DELAY_US(200);
344 putreg(p, DM_EPCR, 0);
345 return getreg(p, DM_EPDRL) | (getreg(p, DM_EPDRH) << 8);
346 }
347
348 // Write a word to PHY
349 static void phy_write(struct dm9000 *p, int offset, cyg_uint16 val)
350 {
351 putreg(p, DM_EPAR, 0x40 + offset);
352 putreg(p, DM_EPDRL, val);
353 putreg(p, DM_EPDRH, val >> 8);
354 putreg(p, DM_EPCR, EPCR_EPOS | EPCR_ERPRW);
355 CYGACC_CALL_IF_DELAY_US(500);
356 putreg(p, DM_EPCR, 0);
357 }
358
359
360 static void init_phy(struct dm9000 *p)
361 {
362 phy_write(p, 4, 0x1e1); // Advertise 10/100 half/full duplex w/CSMA
363 phy_write(p, 0, 0x1200); // enable autoneg
364
365 // release reset
366 putreg(p, DM_GPCR, 1);
367 putreg(p, DM_GPR, 0);
368 }
369
370
371 static inline void dm9000_reset(struct dm9000 *p)
372 {
373 putreg(p, DM_NCR, NCR_RST);
374 CYGACC_CALL_IF_DELAY_US(100);
375 }
376
377 static int initialize_nic(struct dm9000 *priv)
378 {
379 int i;
380
381 dm9000_reset(priv);
382
383 switch (getreg(priv, DM_ISR) >> 6) {
384 case 0:
385 priv->read_data = read_data_16;
386 priv->write_data = write_data_16;
387 priv->buswidth = 2;
388 break;
389 case 1:
390 priv->read_data = read_data_32;
391 priv->write_data = write_data_32;
392 priv->buswidth = 4;
393 break;
394 case 2:
395 priv->read_data = read_data_8;
396 priv->write_data = write_data_8;
397 priv->buswidth = 1;
398 break;
399 default:
400 diag_printf("Unknown DM9000 bus i/f.\n");
401 return 0;
402 }
403
404 init_phy(priv);
405
406 putreg(priv, DM_TCR, 0);
407 putreg(priv, DM_BPTR, 0x3f);
408 putreg(priv, DM_FCTR, 0x38);
409 putreg(priv, DM_FCR, 0xff);
410 putreg(priv, DM_SMCR, 0);
411 putreg(priv, DM_NSR, NSR_WAKEST | NSR_TX1END | NSR_TX2END);
412 putreg(priv, DM_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
413
414 // set MAC address
415 for (i = 0; i < 6; i++)
416 putreg(priv, DM_PAR + i, priv->mac_address[i]);
417
418 // clear multicast table except for broadcast address
419 for (i = 0; i < 6; i++)
420 putreg(priv, DM_MAR + i, 0x00);
421 putreg(priv, DM_MAR + 6, 0x00);
422 putreg(priv, DM_MAR + 7, 0x80);
423
424 return 1;
425 }
426
427
428 // ------------------------------------------------------------------------
429 //
430 // API Function : dm9000_init
431 //
432 // ------------------------------------------------------------------------
433 static bool
434 dm9000_init(struct cyg_netdevtab_entry * ndp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -