ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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 __hppa__
94         unsigned char *ee_data = tp->eeprom;
95
96         if (ee_data[0] == 0x3c && ee_data[1] == 0x10 && 
97                 (ee_data[2] == 0x63 || ee_data[2] == 0x61) && ee_data[3] == 0x10) {
98
99                 static unsigned char leafdata[] =
100                         { 0x01,       /* phy number */
101                           0x02,       /* gpr setup sequence length */
102                           0x02, 0x00, /* gpr setup sequence */
103                           0x02,       /* phy reset sequence length */
104                           0x01, 0x00, /* phy reset sequence */
105                           0x00, 0x78, /* media capabilities */
106                           0x00, 0xe0, /* nway advertisment */
107                           0x00, 0x05, /* fdx bit map */
108                           0x00, 0x06  /* ttm bit map */
109                         };
110
111                 tp->mtable = (struct mediatable *)
112                         kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
113
114                 if (tp->mtable == NULL)
115                         return; /* Horrible, impossible failure. */
116
117                 tp->mtable->defaultmedia = 0x800;
118                 tp->mtable->leafcount = 1;
119                 tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
120                 tp->mtable->has_nonmii = 0;
121                 tp->mtable->has_reset = 0;
122                 tp->mtable->has_mii = 1;
123                 tp->mtable->csr15dir = tp->mtable->csr15val = 0;
124                 tp->mtable->mleaf[0].type = 1;
125                 tp->mtable->mleaf[0].media = 11;
126                 tp->mtable->mleaf[0].leafdata = &leafdata[0];
127                 tp->flags |= HAS_PHY_IRQ;
128                 tp->csr12_shadow = -1;
129         }
130 #endif 
131 }
132
133 void __devinit tulip_parse_eeprom(struct net_device *dev)
134 {
135         /* The last media info list parsed, for multiport boards.  */
136         static struct mediatable *last_mediatable;
137         static unsigned char *last_ee_data;
138         static int controller_index;
139         struct tulip_private *tp = netdev_priv(dev);
140         unsigned char *ee_data = tp->eeprom;
141         int i;
142
143         tp->mtable = 0;
144         /* Detect an old-style (SA only) EEPROM layout:
145            memcmp(eedata, eedata+16, 8). */
146         for (i = 0; i < 8; i ++)
147                 if (ee_data[i] != ee_data[16+i])
148                         break;
149         if (i >= 8) {
150                 if (ee_data[0] == 0xff) {
151                         if (last_mediatable) {
152                                 controller_index++;
153                                 printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
154                                            dev->name, controller_index);
155                                 tp->mtable = last_mediatable;
156                                 ee_data = last_ee_data;
157                                 goto subsequent_board;
158                         } else
159                                 printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
160                                            "not work correctly!\n",
161                            dev->name);
162                         return;
163                 }
164           /* Do a fix-up based on the vendor half of the station address prefix. */
165           for (i = 0; eeprom_fixups[i].name; i++) {
166                 if (dev->dev_addr[0] == eeprom_fixups[i].addr0
167                         &&  dev->dev_addr[1] == eeprom_fixups[i].addr1
168                         &&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
169                   if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
170                           i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
171                   memcpy(ee_data + 26, eeprom_fixups[i].newtable,
172                                  sizeof(eeprom_fixups[i].newtable));
173                   printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
174                                  " substitute media control info.\n",
175                                  dev->name, eeprom_fixups[i].name);
176                   break;
177                 }
178           }
179           if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
180                   printk(KERN_INFO "%s: Old style EEPROM with no media selection "
181                                  "information.\n",
182                            dev->name);
183                 return;
184           }
185         }
186
187         controller_index = 0;
188         if (ee_data[19] > 1) {          /* Multiport board. */
189                 last_ee_data = ee_data;
190         }
191 subsequent_board:
192
193         if (ee_data[27] == 0) {         /* No valid media table. */
194                 tulip_build_fake_mediatable(tp);
195         } else {
196                 unsigned char *p = (void *)ee_data + ee_data[27];
197                 unsigned char csr12dir = 0;
198                 int count, new_advertise = 0;
199                 struct mediatable *mtable;
200                 u16 media = get_u16(p);
201
202                 p += 2;
203                 if (tp->flags & CSR12_IN_SROM)
204                         csr12dir = *p++;
205                 count = *p++;
206
207                 /* there is no phy information, don't even try to build mtable */
208                 if (count == 0) {
209                         if (tulip_debug > 0)
210                                 printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
211                         return;
212                 }
213
214                 mtable = (struct mediatable *)
215                         kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
216                                         GFP_KERNEL);
217                 if (mtable == NULL)
218                         return;                         /* Horrible, impossible failure. */
219                 last_mediatable = tp->mtable = mtable;
220                 mtable->defaultmedia = media;
221                 mtable->leafcount = count;
222                 mtable->csr12dir = csr12dir;
223                 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
224                 mtable->csr15dir = mtable->csr15val = 0;
225
226                 printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
227                            media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
228                 for (i = 0; i < count; i++) {
229                         struct medialeaf *leaf = &mtable->mleaf[i];
230
231                         if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
232                                 leaf->type = 0;
233                                 leaf->media = p[0] & 0x3f;
234                                 leaf->leafdata = p;
235                                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
236                                         mtable->has_mii = 1;
237                                 p += 4;
238                         } else {
239                                 leaf->type = p[1];
240                                 if (p[1] == 0x05) {
241                                         mtable->has_reset = i;
242                                         leaf->media = p[2] & 0x0f;
243                                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
244                                         /* Hack to ignore Davicom delay period block */
245                                         mtable->leafcount--;
246                                         count--;
247                                         i--;
248                                         leaf->leafdata = p + 2;
249                                         p += (p[0] & 0x3f) + 1;
250                                         continue;
251                                 } else if (p[1] & 1) {
252                                         int gpr_len, reset_len;
253
254                                         mtable->has_mii = 1;
255                                         leaf->media = 11;
256                                         gpr_len=p[3]*2;
257                                         reset_len=p[4+gpr_len]*2;
258                                         new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
259                                 } else {
260                                         mtable->has_nonmii = 1;
261                                         leaf->media = p[2] & MEDIA_MASK;
262                                         /* Davicom's media number for 100BaseTX is strange */
263                                         if (tp->chip_id == DM910X && leaf->media == 1)
264                                                 leaf->media = 3;
265                                         switch (leaf->media) {
266                                         case 0: new_advertise |= 0x0020; break;
267                                         case 4: new_advertise |= 0x0040; break;
268                                         case 3: new_advertise |= 0x0080; break;
269                                         case 5: new_advertise |= 0x0100; break;
270                                         case 6: new_advertise |= 0x0200; break;
271                                         }
272                                         if (p[1] == 2  &&  leaf->media == 0) {
273                                                 if (p[2] & 0x40) {
274                                                         u32 base15 = get_unaligned((u16*)&p[7]);
275                                                         mtable->csr15dir =
276                                                                 (get_unaligned((u16*)&p[9])<<16) + base15;
277                                                         mtable->csr15val =
278                                                                 (get_unaligned((u16*)&p[11])<<16) + base15;
279                                                 } else {
280                                                         mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
281                                                         mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
282                                                 }
283                                         }
284                                 }
285                                 leaf->leafdata = p + 2;
286                                 p += (p[0] & 0x3f) + 1;
287                         }
288                         if (tulip_debug > 1  &&  leaf->media == 11) {
289                                 unsigned char *bp = leaf->leafdata;
290                                 printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
291                                            "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
292                                            dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
293                                            bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
294                         }
295                         printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
296                                    "by a %s (%d) block.\n",
297                                    dev->name, i, medianame[leaf->media & 15], leaf->media,
298                                    leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
299                                    leaf->type);
300                 }
301                 if (new_advertise)
302                         tp->sym_advertise = new_advertise;
303         }
304 }
305 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
306
307 /*  EEPROM_Ctrl bits. */
308 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
309 #define EE_CS                   0x01    /* EEPROM chip select. */
310 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
311 #define EE_WRITE_0              0x01
312 #define EE_WRITE_1              0x05
313 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
314 #define EE_ENB                  (0x4800 | EE_CS)
315
316 /* Delay between EEPROM clock transitions.
317    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
318    We add a bus turn-around to insure that this remains true. */
319 #define eeprom_delay()  inl(ee_addr)
320
321 /* The EEPROM commands include the alway-set leading bit. */
322 #define EE_READ_CMD             (6)
323
324 /* Note: this routine returns extra data bits for size detection. */
325 int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len)
326 {
327         int i;
328         unsigned retval = 0;
329         long ee_addr = ioaddr + CSR9;
330         int read_cmd = location | (EE_READ_CMD << addr_len);
331
332         outl(EE_ENB & ~EE_CS, ee_addr);
333         outl(EE_ENB, ee_addr);
334
335         /* Shift the read command bits out. */
336         for (i = 4 + addr_len; i >= 0; i--) {
337                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
338                 outl(EE_ENB | dataval, ee_addr);
339                 eeprom_delay();
340                 outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
341                 eeprom_delay();
342                 retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
343         }
344         outl(EE_ENB, ee_addr);
345         eeprom_delay();
346
347         for (i = 16; i > 0; i--) {
348                 outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
349                 eeprom_delay();
350                 retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
351                 outl(EE_ENB, ee_addr);
352                 eeprom_delay();
353         }
354
355         /* Terminate the EEPROM access. */
356         outl(EE_ENB & ~EE_CS, ee_addr);
357         return retval;
358 }
359