patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / net / tulip / eeprom.c
1 /*
2         drivers/net/tulip/eeprom.c
3
4         Maintained by Jeff Garzik <jgarzik@pobox.com>
5         Copyright 2000,2001  The Linux Kernel Team
6         Written/copyright 1994-2001 by Donald Becker.
7
8         This software may be used and distributed according to the terms
9         of the GNU General Public License, incorporated herein by reference.
10
11         Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
12         for more information on this driver, or visit the project
13         Web page at http://sourceforge.net/projects/tulip/
14
15 */
16
17 #include "tulip.h"
18 #include <linux/init.h>
19 #include <asm/unaligned.h>
20
21
22
23 /* Serial EEPROM section. */
24 /* The main routine to parse the very complicated SROM structure.
25    Search www.digital.com for "21X4 SROM" to get details.
26    This code is very complex, and will require changes to support
27    additional cards, so I'll be verbose about what is going on.
28    */
29
30 /* Known cards that have old-style EEPROMs. */
31 static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
32   {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
33                           0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
34   {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
35                            0x0000, 0x009E, /* 10baseT */
36                            0x0004, 0x009E, /* 10baseT-FD */
37                            0x0903, 0x006D, /* 100baseTx */
38                            0x0905, 0x006D, /* 100baseTx-FD */ }},
39   {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
40                                  0x0107, 0x8021, /* 100baseFx */
41                                  0x0108, 0x8021, /* 100baseFx-FD */
42                                  0x0100, 0x009E, /* 10baseT */
43                                  0x0104, 0x009E, /* 10baseT-FD */
44                                  0x0103, 0x006D, /* 100baseTx */
45                                  0x0105, 0x006D, /* 100baseTx-FD */ }},
46   {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
47                                    0x1001, 0x009E, /* 10base2, CSR12 0x10*/
48                                    0x0000, 0x009E, /* 10baseT */
49                                    0x0004, 0x009E, /* 10baseT-FD */
50                                    0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
51                                    0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
52   {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
53                                   0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
54                                   0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
55                                   0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
56                                   0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
57                                   0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
58    }},
59   {"NetWinder", 0x00, 0x10, 0x57,
60         /* Default media = MII
61          * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
62          */
63         { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
64   },
65   {0, 0, 0, 0, {}}};
66
67
68 static const char *block_name[] __devinitdata = {
69         "21140 non-MII",
70         "21140 MII PHY",
71         "21142 Serial PHY",
72         "21142 MII PHY",
73         "21143 SYM PHY",
74         "21143 reset method"
75 };
76
77
78 /**
79  * tulip_build_fake_mediatable - Build a fake mediatable entry.
80  * @tp: Ptr to the tulip private data.
81  *
82  * Some cards like the 3x5 HSC cards (J3514A) do not have a standard 
83  * srom and can not be handled under the fixup routine.  These cards
84  * still need a valid mediatable entry for correct csr12 setup and 
85  * mii handling.
86  * 
87  * Since this is currently a parisc-linux specific function, the
88  * #ifdef __hppa__ should completely optimize this function away for
89  * non-parisc hardware.
90  */
91 static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
92 {
93 #ifdef CONFIG_GSC
94         if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
95                 static unsigned char leafdata[] =
96                         { 0x01,       /* phy number */
97                           0x02,       /* gpr setup sequence length */
98                           0x02, 0x00, /* gpr setup sequence */
99                           0x02,       /* phy reset sequence length */
100                           0x01, 0x00, /* phy reset sequence */
101                           0x00, 0x78, /* media capabilities */
102                           0x00, 0xe0, /* nway advertisment */
103                           0x00, 0x05, /* fdx bit map */
104                           0x00, 0x06  /* ttm bit map */
105                         };
106
107                 tp->mtable = (struct mediatable *)
108                         kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
109
110                 if (tp->mtable == NULL)
111                         return; /* Horrible, impossible failure. */
112
113                 tp->mtable->defaultmedia = 0x800;
114                 tp->mtable->leafcount = 1;
115                 tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
116                 tp->mtable->has_nonmii = 0;
117                 tp->mtable->has_reset = 0;
118                 tp->mtable->has_mii = 1;
119                 tp->mtable->csr15dir = tp->mtable->csr15val = 0;
120                 tp->mtable->mleaf[0].type = 1;
121                 tp->mtable->mleaf[0].media = 11;
122                 tp->mtable->mleaf[0].leafdata = &leafdata[0];
123                 tp->flags |= HAS_PHY_IRQ;
124                 tp->csr12_shadow = -1;
125         }
126 #endif 
127 }
128
129 void __devinit tulip_parse_eeprom(struct net_device *dev)
130 {
131         /* The last media info list parsed, for multiport boards.  */
132         static struct mediatable *last_mediatable;
133         static unsigned char *last_ee_data;
134         static int controller_index;
135         struct tulip_private *tp = netdev_priv(dev);
136         unsigned char *ee_data = tp->eeprom;
137         int i;
138
139         tp->mtable = 0;
140         /* Detect an old-style (SA only) EEPROM layout:
141            memcmp(eedata, eedata+16, 8). */
142         for (i = 0; i < 8; i ++)
143                 if (ee_data[i] != ee_data[16+i])
144                         break;
145         if (i >= 8) {
146                 if (ee_data[0] == 0xff) {
147                         if (last_mediatable) {
148                                 controller_index++;
149                                 printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
150                                            dev->name, controller_index);
151                                 tp->mtable = last_mediatable;
152                                 ee_data = last_ee_data;
153                                 goto subsequent_board;
154                         } else
155                                 printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
156                                            "not work correctly!\n",
157                            dev->name);
158                         return;
159                 }
160           /* Do a fix-up based on the vendor half of the station address prefix. */
161           for (i = 0; eeprom_fixups[i].name; i++) {
162                 if (dev->dev_addr[0] == eeprom_fixups[i].addr0
163                         &&  dev->dev_addr[1] == eeprom_fixups[i].addr1
164                         &&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
165                   if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
166                           i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
167                   memcpy(ee_data + 26, eeprom_fixups[i].newtable,
168                                  sizeof(eeprom_fixups[i].newtable));
169                   printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
170                                  " substitute media control info.\n",
171                                  dev->name, eeprom_fixups[i].name);
172                   break;
173                 }
174           }
175           if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
176                   printk(KERN_INFO "%s: Old style EEPROM with no media selection "
177                                  "information.\n",
178                            dev->name);
179                 return;
180           }
181         }
182
183         controller_index = 0;
184         if (ee_data[19] > 1) {          /* Multiport board. */
185                 last_ee_data = ee_data;
186         }
187 subsequent_board:
188
189         if (ee_data[27] == 0) {         /* No valid media table. */
190                 tulip_build_fake_mediatable(tp);
191         } else {
192                 unsigned char *p = (void *)ee_data + ee_data[27];
193                 unsigned char csr12dir = 0;
194                 int count, new_advertise = 0;
195                 struct mediatable *mtable;
196                 u16 media = get_u16(p);
197
198                 p += 2;
199                 if (tp->flags & CSR12_IN_SROM)
200                         csr12dir = *p++;
201                 count = *p++;
202
203                 /* there is no phy information, don't even try to build mtable */
204                 if (count == 0) {
205                         if (tulip_debug > 0)
206                                 printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
207                         return;
208                 }
209
210                 mtable = (struct mediatable *)
211                         kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
212                                         GFP_KERNEL);
213                 if (mtable == NULL)
214                         return;                         /* Horrible, impossible failure. */
215                 last_mediatable = tp->mtable = mtable;
216                 mtable->defaultmedia = media;
217                 mtable->leafcount = count;
218                 mtable->csr12dir = csr12dir;
219                 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
220                 mtable->csr15dir = mtable->csr15val = 0;
221
222                 printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
223                            media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
224                 for (i = 0; i < count; i++) {
225                         struct medialeaf *leaf = &mtable->mleaf[i];
226
227                         if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
228                                 leaf->type = 0;
229                                 leaf->media = p[0] & 0x3f;
230                                 leaf->leafdata = p;
231                                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
232                                         mtable->has_mii = 1;
233                                 p += 4;
234                         } else {
235                                 leaf->type = p[1];
236                                 if (p[1] == 0x05) {
237                                         mtable->has_reset = i;
238                                         leaf->media = p[2] & 0x0f;
239                                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
240                                         /* Hack to ignore Davicom delay period block */
241                                         mtable->leafcount--;
242                                         count--;
243                                         i--;
244                                         leaf->leafdata = p + 2;
245                                         p += (p[0] & 0x3f) + 1;
246                                         continue;
247                                 } else if (p[1] & 1) {
248                                         int gpr_len, reset_len;
249
250                                         mtable->has_mii = 1;
251                                         leaf->media = 11;
252                                         gpr_len=p[3]*2;
253                                         reset_len=p[4+gpr_len]*2;
254                                         new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
255                                 } else {
256                                         mtable->has_nonmii = 1;
257                                         leaf->media = p[2] & MEDIA_MASK;
258                                         /* Davicom's media number for 100BaseTX is strange */
259                                         if (tp->chip_id == DM910X && leaf->media == 1)
260                                                 leaf->media = 3;
261                                         switch (leaf->media) {
262                                         case 0: new_advertise |= 0x0020; break;
263                                         case 4: new_advertise |= 0x0040; break;
264                                         case 3: new_advertise |= 0x0080; break;
265                                         case 5: new_advertise |= 0x0100; break;
266                                         case 6: new_advertise |= 0x0200; break;
267                                         }
268                                         if (p[1] == 2  &&  leaf->media == 0) {
269                                                 if (p[2] & 0x40) {
270                                                         u32 base15 = get_unaligned((u16*)&p[7]);
271                                                         mtable->csr15dir =
272                                                                 (get_unaligned((u16*)&p[9])<<16) + base15;
273                                                         mtable->csr15val =
274                                                                 (get_unaligned((u16*)&p[11])<<16) + base15;
275                                                 } else {
276                                                         mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
277                                                         mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
278                                                 }
279                                         }
280                                 }
281                                 leaf->leafdata = p + 2;
282                                 p += (p[0] & 0x3f) + 1;
283                         }
284                         if (tulip_debug > 1  &&  leaf->media == 11) {
285                                 unsigned char *bp = leaf->leafdata;
286                                 printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
287                                            "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
288                                            dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
289                                            bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
290                         }
291                         printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
292                                    "by a %s (%d) block.\n",
293                                    dev->name, i, medianame[leaf->media & 15], leaf->media,
294                                    leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
295                                    leaf->type);
296                 }
297                 if (new_advertise)
298                         tp->sym_advertise = new_advertise;
299         }
300 }
301 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
302
303 /*  EEPROM_Ctrl bits. */
304 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
305 #define EE_CS           0x01    /* EEPROM chip select. */
306 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
307 #define EE_WRITE_0      0x01
308 #define EE_WRITE_1      0x05
309 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
310 #define EE_ENB          (0x4800 | EE_CS)
311
312 /* Delay between EEPROM clock transitions.
313    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
314    We add a bus turn-around to insure that this remains true. */
315 #define eeprom_delay()  inl(ee_addr)
316
317 /* The EEPROM commands include the alway-set leading bit. */
318 #define EE_READ_CMD             (6)
319
320 /* Note: this routine returns extra data bits for size detection. */
321 int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
322 {
323         int i;
324         unsigned retval = 0;
325         struct tulip_private *tp = dev->priv;
326         long ee_addr = tp->base_addr + CSR9;
327         int read_cmd = location | (EE_READ_CMD << addr_len);
328
329         outl(EE_ENB & ~EE_CS, ee_addr);
330         outl(EE_ENB, ee_addr);
331
332         /* Shift the read command bits out. */
333         for (i = 4 + addr_len; i >= 0; i--) {
334                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
335                 outl(EE_ENB | dataval, ee_addr);
336                 eeprom_delay();
337                 outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
338                 eeprom_delay();
339                 retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
340         }
341         outl(EE_ENB, ee_addr);
342         eeprom_delay();
343
344         for (i = 16; i > 0; i--) {
345                 outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
346                 eeprom_delay();
347                 retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
348                 outl(EE_ENB, ee_addr);
349                 eeprom_delay();
350         }
351
352         /* Terminate the EEPROM access. */
353         outl(EE_ENB & ~EE_CS, ee_addr);
354         return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
355 }
356