pvrusb2: reduce stack usage pvr2_eeprom_analyze()
[linux/fpc-iii.git] / drivers / net / ethernet / dec / tulip / eeprom.c
blob1812f4916917e41ee58e42170444aa38a199a19f
1 /*
2 drivers/net/ethernet/dec/tulip/eeprom.c
4 Copyright 2000,2001 The Linux Kernel Team
5 Written/copyright 1994-2001 by Donald Becker.
7 This software may be used and distributed according to the terms
8 of the GNU General Public License, incorporated herein by reference.
10 Please submit bug reports to http://bugzilla.kernel.org/.
13 #include <linux/pci.h>
14 #include <linux/slab.h>
15 #include "tulip.h"
16 #include <asm/unaligned.h>
20 /* Serial EEPROM section. */
21 /* The main routine to parse the very complicated SROM structure.
22 Search www.digital.com for "21X4 SROM" to get details.
23 This code is very complex, and will require changes to support
24 additional cards, so I'll be verbose about what is going on.
27 /* Known cards that have old-style EEPROMs. */
28 static struct eeprom_fixup eeprom_fixups[] = {
29 {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
30 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
31 {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
32 0x0000, 0x009E, /* 10baseT */
33 0x0004, 0x009E, /* 10baseT-FD */
34 0x0903, 0x006D, /* 100baseTx */
35 0x0905, 0x006D, /* 100baseTx-FD */ }},
36 {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
37 0x0107, 0x8021, /* 100baseFx */
38 0x0108, 0x8021, /* 100baseFx-FD */
39 0x0100, 0x009E, /* 10baseT */
40 0x0104, 0x009E, /* 10baseT-FD */
41 0x0103, 0x006D, /* 100baseTx */
42 0x0105, 0x006D, /* 100baseTx-FD */ }},
43 {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
44 0x1001, 0x009E, /* 10base2, CSR12 0x10*/
45 0x0000, 0x009E, /* 10baseT */
46 0x0004, 0x009E, /* 10baseT-FD */
47 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
48 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
49 {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
50 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
51 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
52 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
53 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
54 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
55 }},
56 {"NetWinder", 0x00, 0x10, 0x57,
57 /* Default media = MII
58 * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
60 { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
62 {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset */
63 0x0000, /* 0 == high offset, 0 == gap */
64 0x0800, /* Default Autoselect */
65 0x8001, /* 1 leaf, extended type, bogus len */
66 0x0003, /* Type 3 (MII), PHY #0 */
67 0x0400, /* 0 init instr, 4 reset instr */
68 0x0801, /* Set control mode, GP0 output */
69 0x0000, /* Drive GP0 Low (RST is active low) */
70 0x0800, /* control mode, GP0 input (undriven) */
71 0x0000, /* clear control mode */
72 0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX */
73 0x01e0, /* Advertise all above */
74 0x5000, /* FDX all above */
75 0x1800, /* Set fast TTM in 100bt modes */
76 0x0000, /* PHY cannot be unplugged */
77 }},
78 {NULL}};
81 static const char *const block_name[] = {
82 "21140 non-MII",
83 "21140 MII PHY",
84 "21142 Serial PHY",
85 "21142 MII PHY",
86 "21143 SYM PHY",
87 "21143 reset method"
91 /**
92 * tulip_build_fake_mediatable - Build a fake mediatable entry.
93 * @tp: Ptr to the tulip private data.
95 * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
96 * srom and can not be handled under the fixup routine. These cards
97 * still need a valid mediatable entry for correct csr12 setup and
98 * mii handling.
100 * Since this is currently a parisc-linux specific function, the
101 * #ifdef __hppa__ should completely optimize this function away for
102 * non-parisc hardware.
104 static void tulip_build_fake_mediatable(struct tulip_private *tp)
106 #ifdef CONFIG_GSC
107 if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
108 static unsigned char leafdata[] =
109 { 0x01, /* phy number */
110 0x02, /* gpr setup sequence length */
111 0x02, 0x00, /* gpr setup sequence */
112 0x02, /* phy reset sequence length */
113 0x01, 0x00, /* phy reset sequence */
114 0x00, 0x78, /* media capabilities */
115 0x00, 0xe0, /* nway advertisement */
116 0x00, 0x05, /* fdx bit map */
117 0x00, 0x06 /* ttm bit map */
120 tp->mtable = kmalloc(sizeof(struct mediatable) +
121 sizeof(struct medialeaf), GFP_KERNEL);
123 if (tp->mtable == NULL)
124 return; /* Horrible, impossible failure. */
126 tp->mtable->defaultmedia = 0x800;
127 tp->mtable->leafcount = 1;
128 tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
129 tp->mtable->has_nonmii = 0;
130 tp->mtable->has_reset = 0;
131 tp->mtable->has_mii = 1;
132 tp->mtable->csr15dir = tp->mtable->csr15val = 0;
133 tp->mtable->mleaf[0].type = 1;
134 tp->mtable->mleaf[0].media = 11;
135 tp->mtable->mleaf[0].leafdata = &leafdata[0];
136 tp->flags |= HAS_PHY_IRQ;
137 tp->csr12_shadow = -1;
139 #endif
142 void tulip_parse_eeprom(struct net_device *dev)
145 dev is not registered at this point, so logging messages can't
146 use dev_<level> or netdev_<level> but dev->name is good via a
147 hack in the caller
150 /* The last media info list parsed, for multiport boards. */
151 static struct mediatable *last_mediatable;
152 static unsigned char *last_ee_data;
153 static int controller_index;
154 struct tulip_private *tp = netdev_priv(dev);
155 unsigned char *ee_data = tp->eeprom;
156 int i;
158 tp->mtable = NULL;
159 /* Detect an old-style (SA only) EEPROM layout:
160 memcmp(eedata, eedata+16, 8). */
161 for (i = 0; i < 8; i ++)
162 if (ee_data[i] != ee_data[16+i])
163 break;
164 if (i >= 8) {
165 if (ee_data[0] == 0xff) {
166 if (last_mediatable) {
167 controller_index++;
168 pr_info("%s: Controller %d of multiport board\n",
169 dev->name, controller_index);
170 tp->mtable = last_mediatable;
171 ee_data = last_ee_data;
172 goto subsequent_board;
173 } else
174 pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
175 dev->name);
176 return;
178 /* Do a fix-up based on the vendor half of the station address prefix. */
179 for (i = 0; eeprom_fixups[i].name; i++) {
180 if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
181 dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
182 dev->dev_addr[2] == eeprom_fixups[i].addr2) {
183 if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
184 i++; /* An Accton EN1207, not an outlaw Maxtech. */
185 memcpy(ee_data + 26, eeprom_fixups[i].newtable,
186 sizeof(eeprom_fixups[i].newtable));
187 pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n",
188 dev->name, eeprom_fixups[i].name);
189 break;
192 if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
193 pr_info("%s: Old style EEPROM with no media selection information\n",
194 dev->name);
195 return;
199 controller_index = 0;
200 if (ee_data[19] > 1) { /* Multiport board. */
201 last_ee_data = ee_data;
203 subsequent_board:
205 if (ee_data[27] == 0) { /* No valid media table. */
206 tulip_build_fake_mediatable(tp);
207 } else {
208 unsigned char *p = (void *)ee_data + ee_data[27];
209 unsigned char csr12dir = 0;
210 int count, new_advertise = 0;
211 struct mediatable *mtable;
212 u16 media = get_u16(p);
214 p += 2;
215 if (tp->flags & CSR12_IN_SROM)
216 csr12dir = *p++;
217 count = *p++;
219 /* there is no phy information, don't even try to build mtable */
220 if (count == 0) {
221 if (tulip_debug > 0)
222 pr_warn("%s: no phy info, aborting mtable build\n",
223 dev->name);
224 return;
227 mtable = kmalloc(sizeof(struct mediatable) +
228 count * sizeof(struct medialeaf),
229 GFP_KERNEL);
230 if (mtable == NULL)
231 return; /* Horrible, impossible failure. */
232 last_mediatable = tp->mtable = mtable;
233 mtable->defaultmedia = media;
234 mtable->leafcount = count;
235 mtable->csr12dir = csr12dir;
236 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
237 mtable->csr15dir = mtable->csr15val = 0;
239 pr_info("%s: EEPROM default media type %s\n",
240 dev->name,
241 media & 0x0800 ? "Autosense"
242 : medianame[media & MEDIA_MASK]);
243 for (i = 0; i < count; i++) {
244 struct medialeaf *leaf = &mtable->mleaf[i];
246 if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
247 leaf->type = 0;
248 leaf->media = p[0] & 0x3f;
249 leaf->leafdata = p;
250 if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
251 mtable->has_mii = 1;
252 p += 4;
253 } else {
254 leaf->type = p[1];
255 if (p[1] == 0x05) {
256 mtable->has_reset = i;
257 leaf->media = p[2] & 0x0f;
258 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
259 /* Hack to ignore Davicom delay period block */
260 mtable->leafcount--;
261 count--;
262 i--;
263 leaf->leafdata = p + 2;
264 p += (p[0] & 0x3f) + 1;
265 continue;
266 } else if (p[1] & 1) {
267 int gpr_len, reset_len;
269 mtable->has_mii = 1;
270 leaf->media = 11;
271 gpr_len=p[3]*2;
272 reset_len=p[4+gpr_len]*2;
273 new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
274 } else {
275 mtable->has_nonmii = 1;
276 leaf->media = p[2] & MEDIA_MASK;
277 /* Davicom's media number for 100BaseTX is strange */
278 if (tp->chip_id == DM910X && leaf->media == 1)
279 leaf->media = 3;
280 switch (leaf->media) {
281 case 0: new_advertise |= 0x0020; break;
282 case 4: new_advertise |= 0x0040; break;
283 case 3: new_advertise |= 0x0080; break;
284 case 5: new_advertise |= 0x0100; break;
285 case 6: new_advertise |= 0x0200; break;
287 if (p[1] == 2 && leaf->media == 0) {
288 if (p[2] & 0x40) {
289 u32 base15 = get_unaligned((u16*)&p[7]);
290 mtable->csr15dir =
291 (get_unaligned((u16*)&p[9])<<16) + base15;
292 mtable->csr15val =
293 (get_unaligned((u16*)&p[11])<<16) + base15;
294 } else {
295 mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
296 mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
300 leaf->leafdata = p + 2;
301 p += (p[0] & 0x3f) + 1;
303 if (tulip_debug > 1 && leaf->media == 11) {
304 unsigned char *bp = leaf->leafdata;
305 pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
306 dev->name,
307 bp[0], bp[1], bp[2 + bp[1]*2],
308 bp[5 + bp[2 + bp[1]*2]*2],
309 bp[4 + bp[2 + bp[1]*2]*2]);
311 pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
312 dev->name,
313 i, medianame[leaf->media & 15], leaf->media,
314 leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
315 leaf->type);
317 if (new_advertise)
318 tp->sym_advertise = new_advertise;
321 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
323 /* EEPROM_Ctrl bits. */
324 #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
325 #define EE_CS 0x01 /* EEPROM chip select. */
326 #define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */
327 #define EE_WRITE_0 0x01
328 #define EE_WRITE_1 0x05
329 #define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */
330 #define EE_ENB (0x4800 | EE_CS)
332 /* Delay between EEPROM clock transitions.
333 Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
334 We add a bus turn-around to insure that this remains true. */
335 #define eeprom_delay() ioread32(ee_addr)
337 /* The EEPROM commands include the alway-set leading bit. */
338 #define EE_READ_CMD (6)
340 /* Note: this routine returns extra data bits for size detection. */
341 int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
343 int i;
344 unsigned retval = 0;
345 struct tulip_private *tp = netdev_priv(dev);
346 void __iomem *ee_addr = tp->base_addr + CSR9;
347 int read_cmd = location | (EE_READ_CMD << addr_len);
349 /* If location is past the end of what we can address, don't
350 * read some other location (ie truncate). Just return zero.
352 if (location > (1 << addr_len) - 1)
353 return 0;
355 iowrite32(EE_ENB & ~EE_CS, ee_addr);
356 iowrite32(EE_ENB, ee_addr);
358 /* Shift the read command bits out. */
359 for (i = 4 + addr_len; i >= 0; i--) {
360 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
361 iowrite32(EE_ENB | dataval, ee_addr);
362 eeprom_delay();
363 iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
364 eeprom_delay();
365 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
367 iowrite32(EE_ENB, ee_addr);
368 eeprom_delay();
370 for (i = 16; i > 0; i--) {
371 iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
372 eeprom_delay();
373 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
374 iowrite32(EE_ENB, ee_addr);
375 eeprom_delay();
378 /* Terminate the EEPROM access. */
379 iowrite32(EE_ENB & ~EE_CS, ee_addr);
380 return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;