2 drivers/net/tulip/media.c
4 Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
5 Copyright 2000 The Linux Kernel Team
6 Written/copyright 1994-1999 by Donald Becker.
8 This software may be used and distributed according to the terms
9 of the GNU Public License, incorporated herein by reference.
11 Please refer to Documentation/networking/tulip.txt for more
12 information on this driver.
19 /* This is a mysterious value that can be written to CSR11 in the 21040 (only)
20 to support a pre-NWay full-duplex signaling mechanism using short frames.
21 No one knows what it should be, but if left at its default value some
22 10base2(!) packets trigger a full-duplex-request interrupt. */
23 #define FULL_DUPLEX_MAGIC 0x6969
26 /* MII transceiver control section.
27 Read and write the MII registers using software-generated serial
28 MDIO protocol. See the MII specifications or DP83840A data sheet
31 int tulip_mdio_read(struct net_device
*dev
, int phy_id
, int location
)
33 struct tulip_private
*tp
= (struct tulip_private
*)dev
->priv
;
35 int read_cmd
= (0xf6 << 10) | (phy_id
<< 5) | location
;
37 long ioaddr
= dev
->base_addr
;
38 long mdio_addr
= ioaddr
+ CSR9
;
40 if (tp
->chip_id
== LC82C168
) {
42 outl(0x60020000 + (phy_id
<<23) + (location
<<18), ioaddr
+ 0xA0);
46 if ( ! ((retval
= inl(ioaddr
+ 0xA0)) & 0x80000000))
47 return retval
& 0xffff;
51 if (tp
->chip_id
== COMET
) {
54 return inl(ioaddr
+ 0xB4 + (location
<<2));
55 else if (location
== 17)
56 return inl(ioaddr
+ 0xD0);
57 else if (location
>= 29 && location
<= 31)
58 return inl(ioaddr
+ 0xD4 + ((location
-29)<<2));
63 /* Establish sync by sending at least 32 logic ones. */
64 for (i
= 32; i
>= 0; i
--) {
65 outl(MDIO_ENB
| MDIO_DATA_WRITE1
, mdio_addr
);
67 outl(MDIO_ENB
| MDIO_DATA_WRITE1
| MDIO_SHIFT_CLK
, mdio_addr
);
70 /* Shift the read command bits out. */
71 for (i
= 15; i
>= 0; i
--) {
72 int dataval
= (read_cmd
& (1 << i
)) ? MDIO_DATA_WRITE1
: 0;
74 outl(MDIO_ENB
| dataval
, mdio_addr
);
76 outl(MDIO_ENB
| dataval
| MDIO_SHIFT_CLK
, mdio_addr
);
79 /* Read the two transition, 16 data, and wire-idle bits. */
80 for (i
= 19; i
> 0; i
--) {
81 outl(MDIO_ENB_IN
, mdio_addr
);
83 retval
= (retval
<< 1) | ((inl(mdio_addr
) & MDIO_DATA_READ
) ? 1 : 0);
84 outl(MDIO_ENB_IN
| MDIO_SHIFT_CLK
, mdio_addr
);
87 return (retval
>>1) & 0xffff;
90 void tulip_mdio_write(struct net_device
*dev
, int phy_id
, int location
, int value
)
92 struct tulip_private
*tp
= (struct tulip_private
*)dev
->priv
;
94 int cmd
= (0x5002 << 16) | (phy_id
<< 23) | (location
<<18) | value
;
95 long ioaddr
= dev
->base_addr
;
96 long mdio_addr
= ioaddr
+ CSR9
;
98 if (tp
->chip_id
== LC82C168
) {
100 outl(cmd
, ioaddr
+ 0xA0);
102 if ( ! (inl(ioaddr
+ 0xA0) & 0x80000000))
108 if (tp
->chip_id
== COMET
) {
112 outl(value
, ioaddr
+ 0xB4 + (location
<<2));
113 else if (location
== 17)
114 outl(value
, ioaddr
+ 0xD0);
115 else if (location
>= 29 && location
<= 31)
116 outl(value
, ioaddr
+ 0xD4 + ((location
-29)<<2));
120 /* Establish sync by sending 32 logic ones. */
121 for (i
= 32; i
>= 0; i
--) {
122 outl(MDIO_ENB
| MDIO_DATA_WRITE1
, mdio_addr
);
124 outl(MDIO_ENB
| MDIO_DATA_WRITE1
| MDIO_SHIFT_CLK
, mdio_addr
);
127 /* Shift the command bits out. */
128 for (i
= 31; i
>= 0; i
--) {
129 int dataval
= (cmd
& (1 << i
)) ? MDIO_DATA_WRITE1
: 0;
130 outl(MDIO_ENB
| dataval
, mdio_addr
);
132 outl(MDIO_ENB
| dataval
| MDIO_SHIFT_CLK
, mdio_addr
);
135 /* Clear out extra bits. */
136 for (i
= 2; i
> 0; i
--) {
137 outl(MDIO_ENB_IN
, mdio_addr
);
139 outl(MDIO_ENB_IN
| MDIO_SHIFT_CLK
, mdio_addr
);
145 /* Set up the transceiver control registers for the selected media type. */
146 void tulip_select_media(struct net_device
*dev
, int startup
)
148 long ioaddr
= dev
->base_addr
;
149 struct tulip_private
*tp
= (struct tulip_private
*)dev
->priv
;
150 struct mediatable
*mtable
= tp
->mtable
;
155 struct medialeaf
*mleaf
= &mtable
->mleaf
[tp
->cur_index
];
156 unsigned char *p
= mleaf
->leafdata
;
157 switch (mleaf
->type
) {
158 case 0: /* 21140 non-MII xcvr. */
160 printk(KERN_DEBUG
"%s: Using a 21140 non-MII transceiver"
161 " with control setting %2.2x.\n",
165 outl(mtable
->csr12dir
| 0x100, ioaddr
+ CSR12
);
166 outl(p
[1], ioaddr
+ CSR12
);
167 new_csr6
= 0x02000000 | ((p
[2] & 0x71) << 18);
171 u32 csr13val
, csr14val
, csr15dir
, csr15val
;
172 for (i
= 0; i
< 5; i
++)
173 setup
[i
] = get_u16(&p
[i
*2 + 1]);
175 dev
->if_port
= p
[0] & 15;
176 if (tulip_media_cap
[dev
->if_port
] & MediaAlwaysFD
)
179 if (startup
&& mtable
->has_reset
) {
180 struct medialeaf
*rleaf
= &mtable
->mleaf
[mtable
->has_reset
];
181 unsigned char *rst
= rleaf
->leafdata
;
183 printk(KERN_DEBUG
"%s: Resetting the transceiver.\n",
185 for (i
= 0; i
< rst
[0]; i
++)
186 outl(get_u16(rst
+ 1 + (i
<<1)) << 16, ioaddr
+ CSR15
);
189 printk(KERN_DEBUG
"%s: 21143 non-MII %s transceiver control "
191 dev
->name
, medianame
[dev
->if_port
], setup
[0], setup
[1]);
192 if (p
[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
195 csr15dir
= (setup
[3]<<16) | setup
[2];
196 csr15val
= (setup
[4]<<16) | setup
[2];
197 outl(0, ioaddr
+ CSR13
);
198 outl(csr14val
, ioaddr
+ CSR14
);
199 outl(csr15dir
, ioaddr
+ CSR15
); /* Direction */
200 outl(csr15val
, ioaddr
+ CSR15
); /* Data */
201 outl(csr13val
, ioaddr
+ CSR13
);
204 csr14val
= 0x0003FF7F;
205 csr15dir
= (setup
[0]<<16) | 0x0008;
206 csr15val
= (setup
[1]<<16) | 0x0008;
207 if (dev
->if_port
<= 4)
208 csr14val
= t21142_csr14
[dev
->if_port
];
210 outl(0, ioaddr
+ CSR13
);
211 outl(csr14val
, ioaddr
+ CSR14
);
213 outl(csr15dir
, ioaddr
+ CSR15
); /* Direction */
214 outl(csr15val
, ioaddr
+ CSR15
); /* Data */
215 if (startup
) outl(csr13val
, ioaddr
+ CSR13
);
218 printk(KERN_DEBUG
"%s: Setting CSR15 to %8.8x/%8.8x.\n",
219 dev
->name
, csr15dir
, csr15val
);
220 if (mleaf
->type
== 4)
221 new_csr6
= 0x82020000 | ((setup
[2] & 0x71) << 18);
223 new_csr6
= 0x82420000;
228 int init_length
= p
[1];
233 new_csr6
= 0x020E0000;
234 if (mleaf
->type
== 3) { /* 21142 */
235 u16
*init_sequence
= (u16
*)(p
+2);
236 u16
*reset_sequence
= &((u16
*)(p
+3))[init_length
];
237 int reset_length
= p
[2 + init_length
*2];
238 misc_info
= reset_sequence
+ reset_length
;
240 for (i
= 0; i
< reset_length
; i
++)
241 outl(get_u16(&reset_sequence
[i
]) << 16, ioaddr
+ CSR15
);
242 for (i
= 0; i
< init_length
; i
++)
243 outl(get_u16(&init_sequence
[i
]) << 16, ioaddr
+ CSR15
);
245 u8
*init_sequence
= p
+ 2;
246 u8
*reset_sequence
= p
+ 3 + init_length
;
247 int reset_length
= p
[2 + init_length
];
248 misc_info
= (u16
*)(reset_sequence
+ reset_length
);
250 outl(mtable
->csr12dir
| 0x100, ioaddr
+ CSR12
);
251 for (i
= 0; i
< reset_length
; i
++)
252 outl(reset_sequence
[i
], ioaddr
+ CSR12
);
254 for (i
= 0; i
< init_length
; i
++)
255 outl(init_sequence
[i
], ioaddr
+ CSR12
);
257 to_advertise
= (get_u16(&misc_info
[1]) & tp
->to_advertise
) | 1;
258 tp
->advertising
[phy_num
] = to_advertise
;
260 printk(KERN_DEBUG
"%s: Advertising %4.4x on PHY %d (%d).\n",
261 dev
->name
, to_advertise
, phy_num
, tp
->phys
[phy_num
]);
262 /* Bogus: put in by a committee? */
263 tulip_mdio_write(dev
, tp
->phys
[phy_num
], 4, to_advertise
);
267 printk(KERN_DEBUG
"%s: Invalid media table selection %d.\n",
268 dev
->name
, mleaf
->type
);
269 new_csr6
= 0x020E0000;
272 printk(KERN_DEBUG
"%s: Using media type %s, CSR12 is %2.2x.\n",
273 dev
->name
, medianame
[dev
->if_port
],
274 inl(ioaddr
+ CSR12
) & 0xff);
275 } else if (tp
->chip_id
== DC21041
) {
276 int port
= dev
->if_port
<= 4 ? dev
->if_port
: 0;
278 printk(KERN_DEBUG
"%s: 21041 using media %s, CSR12 is %4.4x.\n",
279 dev
->name
, medianame
[port
== 3 ? 12: port
],
280 inl(ioaddr
+ CSR12
));
281 outl(0x00000000, ioaddr
+ CSR13
); /* Reset the serial interface */
282 outl(t21041_csr14
[port
], ioaddr
+ CSR14
);
283 outl(t21041_csr15
[port
], ioaddr
+ CSR15
);
284 outl(t21041_csr13
[port
], ioaddr
+ CSR13
);
285 new_csr6
= 0x80020000;
286 } else if (tp
->chip_id
== LC82C168
) {
287 if (startup
&& ! tp
->medialock
)
288 dev
->if_port
= tp
->mii_cnt
? 11 : 0;
290 printk(KERN_DEBUG
"%s: PNIC PHY status is %3.3x, media %s.\n",
291 dev
->name
, inl(ioaddr
+ 0xB8), medianame
[dev
->if_port
]);
293 new_csr6
= 0x810C0000;
294 outl(0x0001, ioaddr
+ CSR15
);
295 outl(0x0201B07A, ioaddr
+ 0xB8);
296 } else if (startup
) {
297 /* Start with 10mbps to do autonegotiation. */
298 outl(0x32, ioaddr
+ CSR12
);
299 new_csr6
= 0x00420000;
300 outl(0x0001B078, ioaddr
+ 0xB8);
301 outl(0x0201B078, ioaddr
+ 0xB8);
302 } else if (dev
->if_port
== 3 || dev
->if_port
== 5) {
303 outl(0x33, ioaddr
+ CSR12
);
304 new_csr6
= 0x01860000;
305 /* Trigger autonegotiation. */
306 outl(startup
? 0x0201F868 : 0x0001F868, ioaddr
+ 0xB8);
308 outl(0x32, ioaddr
+ CSR12
);
309 new_csr6
= 0x00420000;
310 outl(0x1F078, ioaddr
+ 0xB8);
312 } else if (tp
->chip_id
== DC21040
) { /* 21040 */
313 /* Turn on the xcvr interface. */
314 int csr12
= inl(ioaddr
+ CSR12
);
316 printk(KERN_DEBUG
"%s: 21040 media type is %s, CSR12 is %2.2x.\n",
317 dev
->name
, medianame
[dev
->if_port
], csr12
);
318 if (tulip_media_cap
[dev
->if_port
] & MediaAlwaysFD
)
321 /* Set the full duplux match frame. */
322 outl(FULL_DUPLEX_MAGIC
, ioaddr
+ CSR11
);
323 outl(0x00000000, ioaddr
+ CSR13
); /* Reset the serial interface */
324 if (t21040_csr13
[dev
->if_port
] & 8) {
325 outl(0x0705, ioaddr
+ CSR14
);
326 outl(0x0006, ioaddr
+ CSR15
);
328 outl(0xffff, ioaddr
+ CSR14
);
329 outl(0x0000, ioaddr
+ CSR15
);
331 outl(0x8f01 | t21040_csr13
[dev
->if_port
], ioaddr
+ CSR13
);
332 } else { /* Unknown chip type with no media table. */
333 if (tp
->default_port
== 0)
334 dev
->if_port
= tp
->mii_cnt
? 11 : 3;
335 if (tulip_media_cap
[dev
->if_port
] & MediaIsMII
) {
336 new_csr6
= 0x020E0000;
337 } else if (tulip_media_cap
[dev
->if_port
] & MediaIsFx
) {
338 new_csr6
= 0x028600000;
340 new_csr6
= 0x038600000;
342 printk(KERN_DEBUG
"%s: No media description table, assuming "
343 "%s transceiver, CSR12 %2.2x.\n",
344 dev
->name
, medianame
[dev
->if_port
],
345 inl(ioaddr
+ CSR12
));
348 tp
->csr6
= new_csr6
| (tp
->csr6
& 0xfdff) | (tp
->full_duplex
? 0x0200 : 0);
353 Check the MII negotiated duplex, and change the CSR6 setting if
355 Return 0 if everything is OK.
356 Return < 0 if the transceiver is missing or has no link beat.
358 int tulip_check_duplex(struct net_device
*dev
)
360 struct tulip_private
*tp
= (struct tulip_private
*)dev
->priv
;
361 int mii_reg1
, mii_reg5
, negotiated
, duplex
;
363 if (tp
->full_duplex_lock
)
365 mii_reg1
= tulip_mdio_read(dev
, tp
->phys
[0], 1);
366 mii_reg5
= tulip_mdio_read(dev
, tp
->phys
[0], 5);
368 printk(KERN_INFO
"%s: MII status %4.4x, Link partner report "
369 "%4.4x.\n", dev
->name
, mii_reg1
, mii_reg5
);
370 if (mii_reg1
== 0xffff)
372 if ((mii_reg1
& 0x0004) == 0) {
373 int new_reg1
= tulip_mdio_read(dev
, tp
->phys
[0], 1);
374 if ((new_reg1
& 0x0004) == 0) {
376 printk(KERN_INFO
"%s: No link beat on the MII interface,"
377 " status %4.4x.\n", dev
->name
, new_reg1
);
381 negotiated
= mii_reg5
& tp
->advertising
[0];
382 duplex
= ((negotiated
& 0x0300) == 0x0100
383 || (negotiated
& 0x00C0) == 0x0040);
384 /* 100baseTx-FD or 10T-FD, but not 100-HD */
385 if (tp
->full_duplex
!= duplex
) {
386 tp
->full_duplex
= duplex
;
387 if (negotiated
& 0x038) /* 100mbps. */
388 tp
->csr6
&= ~0x00400000;
389 if (tp
->full_duplex
) tp
->csr6
|= 0x0200;
390 else tp
->csr6
&= ~0x0200;
391 tulip_restart_rxtx(tp
, tp
->csr6
);
393 printk(KERN_INFO
"%s: Setting %s-duplex based on MII"
394 "#%d link partner capability of %4.4x.\n",
395 dev
->name
, tp
->full_duplex
? "full" : "half",
396 tp
->phys
[0], mii_reg5
);