1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75#include <common.h>
76#include <command.h>
77
78
79#include "ne2000_base.h"
80
81
82
83#include "8390.h"
84
85
86
87
88
89
90
91#define DELAY_OUTPUT 0x01
92#define HAS_MISC_REG 0x02
93#define USE_BIG_BUF 0x04
94#define HAS_IBM_MISC 0x08
95#define IS_DL10019 0x10
96#define IS_DL10022 0x20
97#define HAS_MII 0x40
98#define USE_SHMEM 0x80
99
100#define AM79C9XX_HOME_PHY 0x00006B90
101#define AM79C9XX_ETH_PHY 0x00006B70
102#define MII_PHYID_REV_MASK 0xfffffff0
103#define MII_PHYID_REG1 0x02
104#define MII_PHYID_REG2 0x03
105
106static hw_info_t hw_info[] = {
107 { 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
108 { 0x0ff0, 0x00, 0x00, 0xf4, 0 },
109 { 0x03f4, 0x00, 0x20, 0xe5, 0 },
110 { 0x4910, 0x00, 0x00, 0x94,
111 DELAY_OUTPUT | HAS_IBM_MISC },
112 { 0x0110, 0x00, 0x40, 0xc7, 0 },
113 { 0x0ff0, 0x00, 0x20, 0xe8, 0 },
114 { 0x0110, 0x00, 0x80, 0x19, 0 },
115 { 0x0040, 0x00, 0x80, 0xc8, 0 },
116 { 0x0110, 0x00, 0x40, 0x33, 0 },
117 { 0x01c0, 0x00, 0x00, 0xb4, 0 },
118 { 0x0ff0, 0x00, 0x00, 0x48,
119 HAS_MISC_REG | HAS_IBM_MISC },
120 { 0xb8, 0x08, 0x00, 0x42, 0 },
121 { 0x01c0, 0x00, 0x40, 0x4c, 0 },
122 { 0x0ff0, 0x08, 0x00, 0x5a,
123 HAS_MISC_REG | HAS_IBM_MISC },
124 { 0x0ff0, 0x00, 0x04, 0xac,
125 HAS_MISC_REG | HAS_IBM_MISC },
126 { 0x0ff0, 0x00, 0x06, 0x29,
127 HAS_MISC_REG | HAS_IBM_MISC },
128 { 0x0374, 0x08, 0x00, 0x5a,
129 HAS_MISC_REG | HAS_IBM_MISC },
130 { 0x0374, 0x00, 0x04, 0xac,
131 HAS_MISC_REG | HAS_IBM_MISC },
132 { 0x0ff0, 0x00, 0x60, 0x87,
133 HAS_MISC_REG | HAS_IBM_MISC },
134 { 0x0374, 0x08, 0x00, 0x17,
135 HAS_MISC_REG | HAS_IBM_MISC },
136 { 0x0374, 0x00, 0xc0, 0xa8,
137 HAS_MISC_REG | HAS_IBM_MISC },
138 { 0x0374, 0x00, 0xa0, 0xb0,
139 HAS_MISC_REG | HAS_IBM_MISC },
140 { 0x0198, 0x00, 0x20, 0xe0,
141 HAS_MISC_REG | HAS_IBM_MISC },
142 { 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
143 { 0x0110, 0x00, 0x40, 0xf6, 0 },
144 { 0x0ff0, 0x00, 0xc0, 0xf0,
145 HAS_MISC_REG | HAS_IBM_MISC },
146 { 0x0ff0, 0xe2, 0x0c, 0x0f,
147 HAS_MISC_REG | HAS_IBM_MISC },
148 { 0x0180, 0x00, 0xc0, 0xf0, 0 },
149 { 0x5000, 0x00, 0x00, 0xe8, 0 },
150 { 0x003a, 0x00, 0x80, 0xc6, 0 },
151 { 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
152 { 0x0ff0, 0x00, 0x00, 0x65,
153 HAS_MISC_REG | HAS_IBM_MISC },
154 { 0x0ff0, 0x00, 0x80, 0x45,
155 HAS_MISC_REG | HAS_IBM_MISC },
156 { 0x07f0, 0x00, 0x20, 0xe0, 0 },
157 { 0x0110, 0x00, 0x40, 0x95, 0 },
158 { 0x0ff0, 0x00, 0x20, 0xcb, 0 },
159 { 0x4000, 0x00, 0xc0, 0x1b,
160 DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
161 { 0x01c0, 0x00, 0xc0, 0x1b, 0 },
162 { 0x0110, 0x00, 0xe0, 0x98, 0 },
163 { 0x0060, 0x00, 0x40, 0x05, 0 },
164 { 0x0ff0, 0x00, 0x00, 0x4c, 0 },
165 { 0x01c8, 0x00, 0xa0, 0x0c, 0 },
166 { 0x0, 0x52, 0x54, 0x00, 0 },
167 { 0x0, 0x0, 0x18, 0x5f, 0 }
168};
169
170#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
171
172#define PCNET_CMD 0x00
173#define PCNET_DATAPORT 0x10
174#define PCNET_RESET 0x1f
175#define PCNET_MISC 0x18
176
177static void pcnet_reset_8390(u8* addr)
178{
179 int i, r;
180
181 n2k_outb(E8390_NODMA + E8390_PAGE0+E8390_STOP, E8390_CMD);
182 PRINTK("cmd (at %lx) is %x\n", addr + E8390_CMD, n2k_inb(E8390_CMD));
183 n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
184 PRINTK("cmd (at %lx) is %x\n", addr + E8390_CMD, n2k_inb(E8390_CMD));
185 n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
186 PRINTK("cmd (at %lx) is %x\n", addr + E8390_CMD, n2k_inb(E8390_CMD));
187 n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
188
189 n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);
190
191 for (i = 0; i < 100; i++) {
192 if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
193 break;
194 PRINTK("got %x in reset\n", r);
195 udelay(100);
196 }
197 n2k_outb(ENISR_RESET, EN0_ISR);
198
199 if (i == 100)
200 printf("pcnet_reset_8390() did not complete.\n");
201}
202
203int get_prom(u8* mac_addr, u8* base_addr)
204{
205 u8 prom[32];
206 int i, j;
207 struct {
208 u_char value, offset;
209 } program_seq[] = {
210 {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
211 {0x48, EN0_DCFG},
212 {0x00, EN0_RCNTLO},
213 {0x00, EN0_RCNTHI},
214 {0x00, EN0_IMR},
215 {0xFF, EN0_ISR},
216 {E8390_RXOFF, EN0_RXCR},
217 {E8390_TXOFF, EN0_TXCR},
218 {32, EN0_RCNTLO},
219 {0x00, EN0_RCNTHI},
220 {0x00, EN0_RSARLO},
221 {0x00, EN0_RSARHI},
222 {E8390_RREAD+E8390_START, E8390_CMD},
223 };
224
225 PRINTK ("trying to get MAC via prom reading\n");
226
227 pcnet_reset_8390 (base_addr);
228
229 mdelay (10);
230
231 for (i = 0; i < ARRAY_SIZE(program_seq); i++)
232 n2k_outb (program_seq[i].value, program_seq[i].offset);
233
234 PRINTK ("PROM:");
235 for (i = 0; i < 32; i++) {
236 prom[i] = n2k_inb (PCNET_DATAPORT);
237 PRINTK (" %02x", prom[i]);
238 }
239 PRINTK ("\n");
240 for (i = 0; i < NR_INFO; i++) {
241 if ((prom[0] == hw_info[i].a0) &&
242 (prom[2] == hw_info[i].a1) &&
243 (prom[4] == hw_info[i].a2)) {
244 PRINTK ("matched board %d\n", i);
245 break;
246 }
247 }
248 if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
249 PRINTK ("on exit i is %d/%ld\n", i, NR_INFO);
250 PRINTK ("MAC address is ");
251 for (j = 0; j < 6; j++) {
252 mac_addr[j] = prom[j << 1];
253 PRINTK ("%02x:", mac_addr[i]);
254 }
255 PRINTK ("\n");
256 return (i < NR_INFO) ? i : 0;
257 }
258 return 0;
259}
260