[e16e8f2] | 1 | /* -*- Mode:C; c-basic-offset:4; -*- */ |
---|
| 2 | |
---|
| 3 | /* |
---|
| 4 | Tulip and clone Etherboot Driver |
---|
| 5 | |
---|
| 6 | By Marty Connor (mdc@etherboot.org) |
---|
| 7 | Copyright (C) 2001 Entity Cyber, Inc. |
---|
| 8 | |
---|
| 9 | This software may be used and distributed according to the terms |
---|
| 10 | of the GNU Public License, incorporated herein by reference. |
---|
| 11 | |
---|
| 12 | As of April 2001 this driver should support most tulip cards that |
---|
| 13 | the Linux tulip driver supports because Donald Becker's Linux media |
---|
| 14 | detection code is now included. |
---|
| 15 | |
---|
| 16 | Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's |
---|
| 17 | Linux Tulip Driver. Supports N-Way speed auto-configuration on |
---|
| 18 | MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards |
---|
| 19 | based on the Macronix MX987x5 chip, such as the SOHOware Fast |
---|
| 20 | model SFA110A, and the LinkSYS model LNE100TX. The NetGear |
---|
| 21 | model FA310X, based on the LC82C168 chip is supported. |
---|
| 22 | The TRENDnet TE100-PCIA NIC which uses a genuine Intel 21143-PD |
---|
| 23 | chipset is supported. Also, Davicom DM9102's. |
---|
| 24 | |
---|
| 25 | Documentation and source code used: |
---|
| 26 | Source for Etherboot driver at |
---|
| 27 | http://etherboot.sourceforge.net/ |
---|
| 28 | MX98715A Data Sheet and MX98715A Application Note |
---|
| 29 | on http://www.macronix.com/ (PDF format files) |
---|
| 30 | Source for Linux tulip driver at |
---|
| 31 | http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html |
---|
| 32 | |
---|
| 33 | Adapted by Ken Yap from |
---|
| 34 | FreeBSD netboot DEC 21143 driver |
---|
| 35 | Author: David Sharp |
---|
| 36 | date: Nov/98 |
---|
| 37 | |
---|
| 38 | Some code fragments were taken from verious places, Ken Yap's |
---|
| 39 | etherboot, FreeBSD's if_de.c, and various Linux related files. |
---|
| 40 | DEC's manuals for the 21143 and SROM format were very helpful. |
---|
| 41 | The Linux de driver development page has a number of links to |
---|
| 42 | useful related information. Have a look at: |
---|
| 43 | ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html |
---|
| 44 | */ |
---|
| 45 | |
---|
| 46 | FILE_LICENCE ( GPL_ANY ); |
---|
| 47 | |
---|
| 48 | /*********************************************************************/ |
---|
| 49 | /* Revision History */ |
---|
| 50 | /*********************************************************************/ |
---|
| 51 | |
---|
| 52 | /* |
---|
| 53 | 08 Feb 2005 Ramesh Chander chhabaramesh at yahoo.co.in added table entries |
---|
| 54 | for SGThomson STE10/100A |
---|
| 55 | 07 Sep 2003 timlegge Multicast Support Added |
---|
| 56 | 11 Apr 2001 mdc [patch to etherboot 4.7.24] |
---|
| 57 | Major rewrite to include Linux tulip driver media detection |
---|
| 58 | code. This driver should support a lot more cards now. |
---|
| 59 | 16 Jul 2000 mdc 0.75b11 |
---|
| 60 | Added support for ADMtek 0985 Centaur-P, a "Comet" tulip clone |
---|
| 61 | which is used on the LinkSYS LNE100TX v4.x cards. We already |
---|
| 62 | support LNE100TX v2.0 cards, which use a different controller. |
---|
| 63 | 04 Jul 2000 jam ? |
---|
| 64 | Added test of status after receiving a packet from the card. |
---|
| 65 | Also uncommented the tulip_disable routine. Stray packets |
---|
| 66 | seemed to be causing problems. |
---|
| 67 | 27 Apr 2000 njl ? |
---|
| 68 | 29 Feb 2000 mdc 0.75b7 |
---|
| 69 | Increased reset delay to 3 seconds because Macronix cards seem to |
---|
| 70 | need more reset time before card comes back to a usable state. |
---|
| 71 | 26 Feb 2000 mdc 0.75b6 |
---|
| 72 | Added a 1 second delay after initializing the transmitter because |
---|
| 73 | some cards seem to need the time or they drop the first packet |
---|
| 74 | transmitted. |
---|
| 75 | 23 Feb 2000 mdc 0.75b5 |
---|
| 76 | removed udelay code and used currticks() for more reliable delay |
---|
| 77 | code in reset pause and sanity timeouts. Added function prototypes |
---|
| 78 | and TX debugging code. |
---|
| 79 | 21 Feb 2000 mdc patch to Etherboot 4.4.3 |
---|
| 80 | Incorporated patches from Bob Edwards and Paul Mackerras of |
---|
| 81 | Linuxcare's OZLabs to deal with inefficiencies in tulip_transmit |
---|
| 82 | and udelay. We now wait for packet transmission to complete |
---|
| 83 | (or sanity timeout). |
---|
| 84 | 04 Feb 2000 Robert.Edwards@anu.edu.au patch to Etherboot 4.4.2 |
---|
| 85 | patch to tulip.c that implements the automatic selection of the MII |
---|
| 86 | interface on cards using the Intel/DEC 21143 reference design, in |
---|
| 87 | particular, the TRENDnet TE100-PCIA NIC which uses a genuine Intel |
---|
| 88 | 21143-PD chipset. |
---|
| 89 | 11 Jan 2000 mdc 0.75b4 |
---|
| 90 | Added support for NetGear FA310TX card based on the LC82C168 |
---|
| 91 | chip. This should also support Lite-On LC82C168 boards. |
---|
| 92 | Added simple MII support. Re-arranged code to better modularize |
---|
| 93 | initializations. |
---|
| 94 | 04 Dec 1999 mdc 0.75b3 |
---|
| 95 | Added preliminary support for LNE100TX PCI cards. Should work for |
---|
| 96 | PNIC2 cards. No MII support, but single interface (RJ45) tulip |
---|
| 97 | cards seem to not care. |
---|
| 98 | 03 Dec 1999 mdc 0.75b2 |
---|
| 99 | Renamed from mx987x5 to tulip, merged in original tulip init code |
---|
| 100 | from tulip.c to support other tulip compatible cards. |
---|
| 101 | 02 Dec 1999 mdc 0.75b1 |
---|
| 102 | Released Beta MX987x5 Driver for code review and testing to netboot |
---|
| 103 | and thinguin mailing lists. |
---|
| 104 | */ |
---|
| 105 | |
---|
| 106 | |
---|
| 107 | /*********************************************************************/ |
---|
| 108 | /* Declarations */ |
---|
| 109 | /*********************************************************************/ |
---|
| 110 | |
---|
| 111 | #include "etherboot.h" |
---|
| 112 | #include "nic.h" |
---|
| 113 | |
---|
| 114 | #include <gpxe/ethernet.h> |
---|
| 115 | #include <gpxe/pci.h> |
---|
| 116 | |
---|
| 117 | /* User settable parameters */ |
---|
| 118 | |
---|
| 119 | #undef TULIP_DEBUG |
---|
| 120 | #undef TULIP_DEBUG_WHERE |
---|
| 121 | #ifdef TULIP_DEBUG |
---|
| 122 | static int tulip_debug = 2; /* 1 normal messages, 0 quiet .. 7 verbose. */ |
---|
| 123 | #endif |
---|
| 124 | |
---|
| 125 | #define TX_TIME_OUT 2*TICKS_PER_SEC |
---|
| 126 | |
---|
| 127 | /* helpful macros if on a big_endian machine for changing byte order. |
---|
| 128 | not strictly needed on Intel */ |
---|
| 129 | #define get_unaligned(ptr) (*(ptr)) |
---|
| 130 | #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) |
---|
| 131 | #define get_u16(ptr) (*(u16 *)(ptr)) |
---|
| 132 | #define virt_to_le32desc(addr) virt_to_bus(addr) |
---|
| 133 | |
---|
| 134 | #define TULIP_IOTYPE PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0 |
---|
| 135 | #define TULIP_SIZE 0x80 |
---|
| 136 | |
---|
| 137 | /* This is a mysterious value that can be written to CSR11 in the 21040 (only) |
---|
| 138 | to support a pre-NWay full-duplex signaling mechanism using short frames. |
---|
| 139 | No one knows what it should be, but if left at its default value some |
---|
| 140 | 10base2(!) packets trigger a full-duplex-request interrupt. */ |
---|
| 141 | #define FULL_DUPLEX_MAGIC 0x6969 |
---|
| 142 | |
---|
| 143 | static const int csr0 = 0x01A00000 | 0x8000; |
---|
| 144 | |
---|
| 145 | /* The possible media types that can be set in options[] are: */ |
---|
| 146 | #define MEDIA_MASK 31 |
---|
| 147 | static const char * const medianame[32] = { |
---|
| 148 | "10baseT", "10base2", "AUI", "100baseTx", |
---|
| 149 | "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx", |
---|
| 150 | "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII", |
---|
| 151 | "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4", |
---|
| 152 | "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19", |
---|
| 153 | }; |
---|
| 154 | |
---|
| 155 | /* This much match tulip_tbl[]! Note 21142 == 21143. */ |
---|
| 156 | enum tulip_chips { |
---|
| 157 | DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3, |
---|
| 158 | LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET, |
---|
| 159 | COMPEX9881, I21145, XIRCOM, SGThomson, /*Ramesh Chander*/ |
---|
| 160 | }; |
---|
| 161 | |
---|
| 162 | enum pci_id_flags_bits { |
---|
| 163 | /* Set PCI command register bits before calling probe1(). */ |
---|
| 164 | PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, |
---|
| 165 | /* Read and map the single following PCI BAR. */ |
---|
| 166 | PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4, |
---|
| 167 | PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400, |
---|
| 168 | PCI_UNUSED_IRQ=0x800, |
---|
| 169 | }; |
---|
| 170 | |
---|
| 171 | struct pci_id_info { |
---|
| 172 | char *name; |
---|
| 173 | struct match_info { |
---|
| 174 | u32 pci, pci_mask, subsystem, subsystem_mask; |
---|
| 175 | u32 revision, revision_mask; /* Only 8 bits. */ |
---|
| 176 | } id; |
---|
| 177 | enum pci_id_flags_bits pci_flags; |
---|
| 178 | int io_size; /* Needed for I/O region check or ioremap(). */ |
---|
| 179 | int drv_flags; /* Driver use, intended as capability flags. */ |
---|
| 180 | }; |
---|
| 181 | |
---|
| 182 | static const struct pci_id_info pci_id_tbl[] = { |
---|
| 183 | { "Digital DC21040 Tulip", { 0x00021011, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 184 | TULIP_IOTYPE, 0x80, DC21040 }, |
---|
| 185 | { "Digital DC21041 Tulip", { 0x00141011, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 186 | TULIP_IOTYPE, 0x80, DC21041 }, |
---|
| 187 | { "Digital DS21140A Tulip", { 0x00091011, 0xffffffff, 0,0, 0x20,0xf0 }, |
---|
| 188 | TULIP_IOTYPE, 0x80, DC21140 }, |
---|
| 189 | { "Digital DS21140 Tulip", { 0x00091011, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 190 | TULIP_IOTYPE, 0x80, DC21140 }, |
---|
| 191 | { "Digital DS21143 Tulip", { 0x00191011, 0xffffffff, 0,0, 65,0xff }, |
---|
| 192 | TULIP_IOTYPE, TULIP_SIZE, DC21142 }, |
---|
| 193 | { "Digital DS21142 Tulip", { 0x00191011, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 194 | TULIP_IOTYPE, TULIP_SIZE, DC21142 }, |
---|
| 195 | { "Kingston KNE110tx (PNIC)", { 0x000211AD, 0xffffffff, 0xf0022646, 0xffffffff, 0, 0 }, |
---|
| 196 | TULIP_IOTYPE, 256, LC82C168 }, |
---|
| 197 | { "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 198 | TULIP_IOTYPE, 256, LC82C168 }, |
---|
| 199 | { "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 200 | TULIP_IOTYPE, 256, MX98713 }, |
---|
| 201 | { "Macronix 98715 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 202 | TULIP_IOTYPE, 256, MX98715 }, |
---|
| 203 | { "Macronix 98725 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 204 | TULIP_IOTYPE, 256, MX98725 }, |
---|
| 205 | { "ASIX AX88141", { 0x1400125B, 0xffffffff, 0,0, 0x10, 0xf0 }, |
---|
| 206 | TULIP_IOTYPE, 128, AX88141 }, |
---|
| 207 | { "ASIX AX88140", { 0x1400125B, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 208 | TULIP_IOTYPE, 128, AX88140 }, |
---|
| 209 | { "Lite-On LC82C115 PNIC-II", { 0xc11511AD, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 210 | TULIP_IOTYPE, 256, PNIC2 }, |
---|
| 211 | { "ADMtek AN981 Comet", { 0x09811317, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 212 | TULIP_IOTYPE, 256, COMET }, |
---|
| 213 | { "ADMTek AN983 Comet", { 0x12161113, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 214 | TULIP_IOTYPE, 256, COMET }, |
---|
| 215 | { "ADMTek Comet AN983b", { 0x95111317, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 216 | TULIP_IOTYPE, 256, COMET }, |
---|
| 217 | { "ADMtek Centaur-P", { 0x09851317, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 218 | TULIP_IOTYPE, 256, COMET }, |
---|
| 219 | { "ADMtek Centaur-C", { 0x19851317, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 220 | TULIP_IOTYPE, 256, COMET }, |
---|
| 221 | { "Compex RL100-TX", { 0x988111F6, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 222 | TULIP_IOTYPE, 128, COMPEX9881 }, |
---|
| 223 | { "Intel 21145 Tulip", { 0x00398086, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 224 | TULIP_IOTYPE, 128, I21145 }, |
---|
| 225 | { "Xircom Tulip clone", { 0x0003115d, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 226 | TULIP_IOTYPE, 128, XIRCOM }, |
---|
| 227 | { "Davicom DM9102", { 0x91021282, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 228 | TULIP_IOTYPE, 0x80, DC21140 }, |
---|
| 229 | { "Davicom DM9100", { 0x91001282, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 230 | TULIP_IOTYPE, 0x80, DC21140 }, |
---|
| 231 | { "Macronix mxic-98715 (EN1217)", { 0x12171113, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 232 | TULIP_IOTYPE, 256, MX98715 }, |
---|
| 233 | { "3Com 3cSOHO100B-TX (ADMtek Centuar)", { 0x930010b7, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 234 | TULIP_IOTYPE, TULIP_SIZE, COMET }, |
---|
| 235 | { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 }, |
---|
| 236 | TULIP_IOTYPE, 256, COMET }, /*Ramesh Chander*/ |
---|
| 237 | { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 }, |
---|
| 238 | }; |
---|
| 239 | |
---|
| 240 | enum tbl_flag { |
---|
| 241 | HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8, |
---|
| 242 | HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */ |
---|
| 243 | HAS_PNICNWAY=0x80, HAS_NWAY=0x40, /* Uses internal NWay xcvr. */ |
---|
| 244 | HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400, |
---|
| 245 | }; |
---|
| 246 | |
---|
| 247 | /* Note: this table must match enum tulip_chips above. */ |
---|
| 248 | static struct tulip_chip_table { |
---|
| 249 | char *chip_name; |
---|
| 250 | int flags; |
---|
| 251 | } tulip_tbl[] = { |
---|
| 252 | { "Digital DC21040 Tulip", 0}, |
---|
| 253 | { "Digital DC21041 Tulip", HAS_MEDIA_TABLE | HAS_NWAY }, |
---|
| 254 | { "Digital DS21140 Tulip", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM }, |
---|
| 255 | { "Digital DS21143 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII |
---|
| 256 | | HAS_PWRDWN | HAS_NWAY | HAS_INTR_MITIGATION }, |
---|
| 257 | { "Lite-On 82c168 PNIC", HAS_MII | HAS_PNICNWAY }, |
---|
| 258 | { "Macronix 98713 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM }, |
---|
| 259 | { "Macronix 98715 PMAC", HAS_MEDIA_TABLE }, |
---|
| 260 | { "Macronix 98725 PMAC", HAS_MEDIA_TABLE }, |
---|
| 261 | { "ASIX AX88140", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM |
---|
| 262 | | MC_HASH_ONLY | IS_ASIX }, |
---|
| 263 | { "ASIX AX88141", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY |
---|
| 264 | | IS_ASIX }, |
---|
| 265 | { "Lite-On PNIC-II", HAS_MII | HAS_NWAY | HAS_8023X }, |
---|
| 266 | { "ADMtek Comet", HAS_MII | MC_HASH_ONLY }, |
---|
| 267 | { "Compex 9881 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM }, |
---|
| 268 | { "Intel DS21145 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII |
---|
| 269 | | HAS_PWRDWN | HAS_NWAY }, |
---|
| 270 | { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII |
---|
| 271 | | HAS_PWRDWN | HAS_NWAY }, |
---|
| 272 | { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY }, /*Ramesh Chander*/ |
---|
| 273 | { 0, 0 }, |
---|
| 274 | }; |
---|
| 275 | |
---|
| 276 | /* A full-duplex map for media types. */ |
---|
| 277 | enum MediaIs { |
---|
| 278 | MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8, |
---|
| 279 | MediaIs100=16}; |
---|
| 280 | |
---|
| 281 | static const char media_cap[32] = |
---|
| 282 | {0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 20,31,0,0, }; |
---|
| 283 | static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0}; |
---|
| 284 | |
---|
| 285 | /* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD */ |
---|
| 286 | static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; |
---|
| 287 | static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; |
---|
| 288 | static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; |
---|
| 289 | |
---|
| 290 | /* not used |
---|
| 291 | static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; |
---|
| 292 | */ |
---|
| 293 | static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; |
---|
| 294 | /* not used |
---|
| 295 | static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; |
---|
| 296 | */ |
---|
| 297 | |
---|
| 298 | /* Offsets to the Command and Status Registers, "CSRs". All accesses |
---|
| 299 | must be longword instructions and quadword aligned. */ |
---|
| 300 | enum tulip_offsets { |
---|
| 301 | CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, |
---|
| 302 | CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, |
---|
| 303 | CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0 |
---|
| 304 | }; |
---|
| 305 | |
---|
| 306 | /* The bits in the CSR5 status registers, mostly interrupt sources. */ |
---|
| 307 | enum status_bits { |
---|
| 308 | TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10, |
---|
| 309 | NormalIntr=0x10000, AbnormalIntr=0x8000, |
---|
| 310 | RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40, |
---|
| 311 | TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01, |
---|
| 312 | }; |
---|
| 313 | |
---|
| 314 | /* The configuration bits in CSR6. */ |
---|
| 315 | enum csr6_mode_bits { |
---|
| 316 | TxOn=0x2000, RxOn=0x0002, FullDuplex=0x0200, |
---|
| 317 | AcceptBroadcast=0x0100, AcceptAllMulticast=0x0080, |
---|
| 318 | AcceptAllPhys=0x0040, AcceptRunt=0x0008, |
---|
| 319 | }; |
---|
| 320 | |
---|
| 321 | |
---|
| 322 | enum desc_status_bits { |
---|
| 323 | DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300, |
---|
| 324 | }; |
---|
| 325 | |
---|
| 326 | struct medialeaf { |
---|
| 327 | u8 type; |
---|
| 328 | u8 media; |
---|
| 329 | unsigned char *leafdata; |
---|
| 330 | }; |
---|
| 331 | |
---|
| 332 | struct mediatable { |
---|
| 333 | u16 defaultmedia; |
---|
| 334 | u8 leafcount, csr12dir; /* General purpose pin directions. */ |
---|
| 335 | unsigned has_mii:1, has_nonmii:1, has_reset:6; |
---|
| 336 | u32 csr15dir, csr15val; /* 21143 NWay setting. */ |
---|
| 337 | struct medialeaf mleaf[0]; |
---|
| 338 | }; |
---|
| 339 | |
---|
| 340 | struct mediainfo { |
---|
| 341 | struct mediainfo *next; |
---|
| 342 | int info_type; |
---|
| 343 | int index; |
---|
| 344 | unsigned char *info; |
---|
| 345 | }; |
---|
| 346 | |
---|
| 347 | /* EEPROM Address width definitions */ |
---|
| 348 | #define EEPROM_ADDRLEN 6 |
---|
| 349 | #define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */ |
---|
| 350 | |
---|
| 351 | /* The EEPROM commands include the alway-set leading bit. */ |
---|
| 352 | #define EE_WRITE_CMD (5 << addr_len) |
---|
| 353 | #define EE_READ_CMD (6 << addr_len) |
---|
| 354 | #define EE_ERASE_CMD (7 << addr_len) |
---|
| 355 | |
---|
| 356 | /* EEPROM_Ctrl bits. */ |
---|
| 357 | #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ |
---|
| 358 | #define EE_CS 0x01 /* EEPROM chip select. */ |
---|
| 359 | #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ |
---|
| 360 | #define EE_WRITE_0 0x01 |
---|
| 361 | #define EE_WRITE_1 0x05 |
---|
| 362 | #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ |
---|
| 363 | #define EE_ENB (0x4800 | EE_CS) |
---|
| 364 | |
---|
| 365 | /* Delay between EEPROM clock transitions. Even at 33Mhz current PCI |
---|
| 366 | implementations don't overrun the EEPROM clock. We add a bus |
---|
| 367 | turn-around to insure that this remains true. */ |
---|
| 368 | #define eeprom_delay() inl(ee_addr) |
---|
| 369 | |
---|
| 370 | /* Size of transmit and receive buffers */ |
---|
| 371 | #define BUFLEN 1536 |
---|
| 372 | |
---|
| 373 | /* Ring-wrap flag in length field, use for last ring entry. |
---|
| 374 | 0x01000000 means chain on buffer2 address, |
---|
| 375 | 0x02000000 means use the ring start address in CSR2/3. |
---|
| 376 | Note: Some work-alike chips do not function correctly in chained mode. |
---|
| 377 | The ASIX chip works only in chained mode. |
---|
| 378 | Thus we indicate ring mode, but always write the 'next' field for |
---|
| 379 | chained mode as well. */ |
---|
| 380 | #define DESC_RING_WRAP 0x02000000 |
---|
| 381 | |
---|
| 382 | /* transmit and receive descriptor format */ |
---|
| 383 | struct tulip_rx_desc { |
---|
| 384 | volatile u32 status; |
---|
| 385 | u32 length; |
---|
| 386 | u32 buffer1, buffer2; |
---|
| 387 | }; |
---|
| 388 | |
---|
| 389 | struct tulip_tx_desc { |
---|
| 390 | volatile u32 status; |
---|
| 391 | u32 length; |
---|
| 392 | u32 buffer1, buffer2; |
---|
| 393 | }; |
---|
| 394 | |
---|
| 395 | /*********************************************************************/ |
---|
| 396 | /* Global Storage */ |
---|
| 397 | /*********************************************************************/ |
---|
| 398 | |
---|
| 399 | static u32 ioaddr; |
---|
| 400 | |
---|
| 401 | struct tulip_private { |
---|
| 402 | int cur_rx; |
---|
| 403 | int chip_id; /* index into tulip_tbl[] */ |
---|
| 404 | int pci_id_idx; /* index into pci_id_tbl[] */ |
---|
| 405 | int revision; |
---|
| 406 | int flags; |
---|
| 407 | unsigned short vendor_id; /* PCI card vendor code */ |
---|
| 408 | unsigned short dev_id; /* PCI card device code */ |
---|
| 409 | unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */ |
---|
| 410 | const char *nic_name; |
---|
| 411 | unsigned int csr0, csr6; /* Current CSR0, CSR6 settings. */ |
---|
| 412 | unsigned int if_port; |
---|
| 413 | unsigned int full_duplex; /* Full-duplex operation requested. */ |
---|
| 414 | unsigned int full_duplex_lock; |
---|
| 415 | unsigned int medialock; /* Do not sense media type. */ |
---|
| 416 | unsigned int mediasense; /* Media sensing in progress. */ |
---|
| 417 | unsigned int nway, nwayset; /* 21143 internal NWay. */ |
---|
| 418 | unsigned int default_port; |
---|
| 419 | unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ |
---|
| 420 | u8 media_table_storage[(sizeof(struct mediatable) + 32*sizeof(struct medialeaf))]; |
---|
| 421 | u16 sym_advertise, mii_advertise; /* NWay to-advertise. */ |
---|
| 422 | struct mediatable *mtable; |
---|
| 423 | u16 lpar; /* 21143 Link partner ability. */ |
---|
| 424 | u16 advertising[4]; /* MII advertise, from SROM table. */ |
---|
| 425 | signed char phys[4], mii_cnt; /* MII device addresses. */ |
---|
| 426 | int cur_index; /* Current media index. */ |
---|
| 427 | int saved_if_port; |
---|
| 428 | }; |
---|
| 429 | |
---|
| 430 | /* Note: transmit and receive buffers must be longword aligned and |
---|
| 431 | longword divisable */ |
---|
| 432 | |
---|
| 433 | #define TX_RING_SIZE 2 |
---|
| 434 | #define RX_RING_SIZE 4 |
---|
| 435 | struct { |
---|
| 436 | struct tulip_tx_desc tx_ring[TX_RING_SIZE]; |
---|
| 437 | unsigned char txb[BUFLEN]; |
---|
| 438 | struct tulip_rx_desc rx_ring[RX_RING_SIZE]; |
---|
| 439 | unsigned char rxb[RX_RING_SIZE * BUFLEN]; |
---|
| 440 | struct tulip_private tpx; |
---|
| 441 | } tulip_bss __shared __attribute__ ((aligned(4))); |
---|
| 442 | #define tx_ring tulip_bss.tx_ring |
---|
| 443 | #define txb tulip_bss.txb |
---|
| 444 | #define rx_ring tulip_bss.rx_ring |
---|
| 445 | #define rxb tulip_bss.rxb |
---|
| 446 | |
---|
| 447 | static struct tulip_private *tp; |
---|
| 448 | |
---|
| 449 | /* Known cards that have old-style EEPROMs. |
---|
| 450 | Writing this table is described at |
---|
| 451 | http://cesdis.gsfc.nasa.gov/linux/drivers/tulip-drivers/tulip-media.html */ |
---|
| 452 | static struct fixups { |
---|
| 453 | char *name; |
---|
| 454 | unsigned char addr0, addr1, addr2; |
---|
| 455 | u16 newtable[32]; /* Max length below. */ |
---|
| 456 | } eeprom_fixups[] = { |
---|
| 457 | {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c, |
---|
| 458 | 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }}, |
---|
| 459 | {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f, |
---|
| 460 | 0x0000, 0x009E, /* 10baseT */ |
---|
| 461 | 0x0004, 0x009E, /* 10baseT-FD */ |
---|
| 462 | 0x0903, 0x006D, /* 100baseTx */ |
---|
| 463 | 0x0905, 0x006D, /* 100baseTx-FD */ }}, |
---|
| 464 | {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f, |
---|
| 465 | 0x0107, 0x8021, /* 100baseFx */ |
---|
| 466 | 0x0108, 0x8021, /* 100baseFx-FD */ |
---|
| 467 | 0x0100, 0x009E, /* 10baseT */ |
---|
| 468 | 0x0104, 0x009E, /* 10baseT-FD */ |
---|
| 469 | 0x0103, 0x006D, /* 100baseTx */ |
---|
| 470 | 0x0105, 0x006D, /* 100baseTx-FD */ }}, |
---|
| 471 | {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513, |
---|
| 472 | 0x1001, 0x009E, /* 10base2, CSR12 0x10*/ |
---|
| 473 | 0x0000, 0x009E, /* 10baseT */ |
---|
| 474 | 0x0004, 0x009E, /* 10baseT-FD */ |
---|
| 475 | 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ |
---|
| 476 | 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}}, |
---|
| 477 | {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F, |
---|
| 478 | 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */ |
---|
| 479 | 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */ |
---|
| 480 | 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */ |
---|
| 481 | 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ |
---|
| 482 | 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */ |
---|
| 483 | }}, |
---|
| 484 | {0, 0, 0, 0, {}}}; |
---|
| 485 | |
---|
| 486 | static const char * block_name[] = {"21140 non-MII", "21140 MII PHY", |
---|
| 487 | "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"}; |
---|
| 488 | |
---|
| 489 | |
---|
| 490 | /*********************************************************************/ |
---|
| 491 | /* Function Prototypes */ |
---|
| 492 | /*********************************************************************/ |
---|
| 493 | static int mdio_read(struct nic *nic, int phy_id, int location); |
---|
| 494 | static void mdio_write(struct nic *nic, int phy_id, int location, int value); |
---|
| 495 | static int read_eeprom(unsigned long ioaddr, int location, int addr_len); |
---|
| 496 | static void parse_eeprom(struct nic *nic); |
---|
| 497 | static int tulip_probe(struct nic *nic,struct pci_device *pci); |
---|
| 498 | static void tulip_init_ring(struct nic *nic); |
---|
| 499 | static void tulip_reset(struct nic *nic); |
---|
| 500 | static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, |
---|
| 501 | unsigned int s, const char *p); |
---|
| 502 | static int tulip_poll(struct nic *nic, int retrieve); |
---|
| 503 | static void tulip_disable(struct nic *nic); |
---|
| 504 | static void nway_start(struct nic *nic); |
---|
| 505 | static void pnic_do_nway(struct nic *nic); |
---|
| 506 | static void select_media(struct nic *nic, int startup); |
---|
| 507 | static void init_media(struct nic *nic); |
---|
| 508 | static void start_link(struct nic *nic); |
---|
| 509 | static int tulip_check_duplex(struct nic *nic); |
---|
| 510 | |
---|
| 511 | static void tulip_wait(unsigned int nticks); |
---|
| 512 | |
---|
| 513 | #ifdef TULIP_DEBUG_WHERE |
---|
| 514 | static void whereami(const char *str); |
---|
| 515 | #endif |
---|
| 516 | |
---|
| 517 | #ifdef TULIP_DEBUG |
---|
| 518 | static void tulip_more(void); |
---|
| 519 | #endif |
---|
| 520 | |
---|
| 521 | |
---|
| 522 | /*********************************************************************/ |
---|
| 523 | /* Utility Routines */ |
---|
| 524 | /*********************************************************************/ |
---|
| 525 | |
---|
| 526 | #ifdef TULIP_DEBUG_WHERE |
---|
| 527 | static void whereami (const char *str, struct pci_device *pci) |
---|
| 528 | { |
---|
| 529 | printf("%s: %s\n", tp->nic_name, str); |
---|
| 530 | /* sleep(2); */ |
---|
| 531 | } |
---|
| 532 | #endif |
---|
| 533 | |
---|
| 534 | #ifdef TULIP_DEBUG |
---|
| 535 | static void tulip_more(void) |
---|
| 536 | { |
---|
| 537 | printf("\n\n-- more --"); |
---|
| 538 | while (!iskey()) |
---|
| 539 | /* wait */; |
---|
| 540 | getchar(); |
---|
| 541 | printf("\n\n"); |
---|
| 542 | } |
---|
| 543 | #endif /* TULIP_DEBUG */ |
---|
| 544 | |
---|
| 545 | static void tulip_wait(unsigned int nticks) |
---|
| 546 | { |
---|
| 547 | unsigned int to = currticks() + nticks; |
---|
| 548 | while (currticks() < to) |
---|
| 549 | /* wait */ ; |
---|
| 550 | } |
---|
| 551 | |
---|
| 552 | |
---|
| 553 | /*********************************************************************/ |
---|
| 554 | /* Media Descriptor Code */ |
---|
| 555 | /*********************************************************************/ |
---|
| 556 | |
---|
| 557 | /* MII transceiver control section. |
---|
| 558 | Read and write the MII registers using software-generated serial |
---|
| 559 | MDIO protocol. See the MII specifications or DP83840A data sheet |
---|
| 560 | for details. */ |
---|
| 561 | |
---|
| 562 | /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually |
---|
| 563 | met by back-to-back PCI I/O cycles, but we insert a delay to avoid |
---|
| 564 | "overclocking" issues or future 66Mhz PCI. */ |
---|
| 565 | #define mdio_delay() inl(mdio_addr) |
---|
| 566 | |
---|
| 567 | /* Read and write the MII registers using software-generated serial |
---|
| 568 | MDIO protocol. It is just different enough from the EEPROM protocol |
---|
| 569 | to not share code. The maxium data clock rate is 2.5 Mhz. */ |
---|
| 570 | #define MDIO_SHIFT_CLK 0x10000 |
---|
| 571 | #define MDIO_DATA_WRITE0 0x00000 |
---|
| 572 | #define MDIO_DATA_WRITE1 0x20000 |
---|
| 573 | #define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ |
---|
| 574 | #define MDIO_ENB_IN 0x40000 |
---|
| 575 | #define MDIO_DATA_READ 0x80000 |
---|
| 576 | |
---|
| 577 | /* MII transceiver control section. |
---|
| 578 | Read and write the MII registers using software-generated serial |
---|
| 579 | MDIO protocol. See the MII specifications or DP83840A data sheet |
---|
| 580 | for details. */ |
---|
| 581 | |
---|
| 582 | int mdio_read(struct nic *nic __unused, int phy_id, int location) |
---|
| 583 | { |
---|
| 584 | int i; |
---|
| 585 | int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; |
---|
| 586 | int retval = 0; |
---|
| 587 | long mdio_addr = ioaddr + CSR9; |
---|
| 588 | |
---|
| 589 | #ifdef TULIP_DEBUG_WHERE |
---|
| 590 | whereami("mdio_read\n"); |
---|
| 591 | #endif |
---|
| 592 | |
---|
| 593 | if (tp->chip_id == LC82C168) { |
---|
| 594 | int i = 1000; |
---|
| 595 | outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); |
---|
| 596 | inl(ioaddr + 0xA0); |
---|
| 597 | inl(ioaddr + 0xA0); |
---|
| 598 | while (--i > 0) |
---|
| 599 | if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000)) |
---|
| 600 | return retval & 0xffff; |
---|
| 601 | return 0xffff; |
---|
| 602 | } |
---|
| 603 | |
---|
| 604 | if (tp->chip_id == COMET) { |
---|
| 605 | if (phy_id == 1) { |
---|
| 606 | if (location < 7) |
---|
| 607 | return inl(ioaddr + 0xB4 + (location<<2)); |
---|
| 608 | else if (location == 17) |
---|
| 609 | return inl(ioaddr + 0xD0); |
---|
| 610 | else if (location >= 29 && location <= 31) |
---|
| 611 | return inl(ioaddr + 0xD4 + ((location-29)<<2)); |
---|
| 612 | } |
---|
| 613 | return 0xffff; |
---|
| 614 | } |
---|
| 615 | |
---|
| 616 | /* Establish sync by sending at least 32 logic ones. */ |
---|
| 617 | for (i = 32; i >= 0; i--) { |
---|
| 618 | outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); |
---|
| 619 | mdio_delay(); |
---|
| 620 | outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 621 | mdio_delay(); |
---|
| 622 | } |
---|
| 623 | /* Shift the read command bits out. */ |
---|
| 624 | for (i = 15; i >= 0; i--) { |
---|
| 625 | int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; |
---|
| 626 | |
---|
| 627 | outl(MDIO_ENB | dataval, mdio_addr); |
---|
| 628 | mdio_delay(); |
---|
| 629 | outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 630 | mdio_delay(); |
---|
| 631 | } |
---|
| 632 | /* Read the two transition, 16 data, and wire-idle bits. */ |
---|
| 633 | for (i = 19; i > 0; i--) { |
---|
| 634 | outl(MDIO_ENB_IN, mdio_addr); |
---|
| 635 | mdio_delay(); |
---|
| 636 | retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); |
---|
| 637 | outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 638 | mdio_delay(); |
---|
| 639 | } |
---|
| 640 | return (retval>>1) & 0xffff; |
---|
| 641 | } |
---|
| 642 | |
---|
| 643 | void mdio_write(struct nic *nic __unused, int phy_id, int location, int value) |
---|
| 644 | { |
---|
| 645 | int i; |
---|
| 646 | int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; |
---|
| 647 | long mdio_addr = ioaddr + CSR9; |
---|
| 648 | |
---|
| 649 | #ifdef TULIP_DEBUG_WHERE |
---|
| 650 | whereami("mdio_write\n"); |
---|
| 651 | #endif |
---|
| 652 | |
---|
| 653 | if (tp->chip_id == LC82C168) { |
---|
| 654 | int i = 1000; |
---|
| 655 | outl(cmd, ioaddr + 0xA0); |
---|
| 656 | do |
---|
| 657 | if ( ! (inl(ioaddr + 0xA0) & 0x80000000)) |
---|
| 658 | break; |
---|
| 659 | while (--i > 0); |
---|
| 660 | return; |
---|
| 661 | } |
---|
| 662 | |
---|
| 663 | if (tp->chip_id == COMET) { |
---|
| 664 | if (phy_id != 1) |
---|
| 665 | return; |
---|
| 666 | if (location < 7) |
---|
| 667 | outl(value, ioaddr + 0xB4 + (location<<2)); |
---|
| 668 | else if (location == 17) |
---|
| 669 | outl(value, ioaddr + 0xD0); |
---|
| 670 | else if (location >= 29 && location <= 31) |
---|
| 671 | outl(value, ioaddr + 0xD4 + ((location-29)<<2)); |
---|
| 672 | return; |
---|
| 673 | } |
---|
| 674 | |
---|
| 675 | /* Establish sync by sending 32 logic ones. */ |
---|
| 676 | for (i = 32; i >= 0; i--) { |
---|
| 677 | outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); |
---|
| 678 | mdio_delay(); |
---|
| 679 | outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 680 | mdio_delay(); |
---|
| 681 | } |
---|
| 682 | /* Shift the command bits out. */ |
---|
| 683 | for (i = 31; i >= 0; i--) { |
---|
| 684 | int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; |
---|
| 685 | outl(MDIO_ENB | dataval, mdio_addr); |
---|
| 686 | mdio_delay(); |
---|
| 687 | outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 688 | mdio_delay(); |
---|
| 689 | } |
---|
| 690 | /* Clear out extra bits. */ |
---|
| 691 | for (i = 2; i > 0; i--) { |
---|
| 692 | outl(MDIO_ENB_IN, mdio_addr); |
---|
| 693 | mdio_delay(); |
---|
| 694 | outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); |
---|
| 695 | mdio_delay(); |
---|
| 696 | } |
---|
| 697 | } |
---|
| 698 | |
---|
| 699 | |
---|
| 700 | /*********************************************************************/ |
---|
| 701 | /* EEPROM Reading Code */ |
---|
| 702 | /*********************************************************************/ |
---|
| 703 | /* EEPROM routines adapted from the Linux Tulip Code */ |
---|
| 704 | /* Reading a serial EEPROM is a "bit" grungy, but we work our way |
---|
| 705 | through:->. |
---|
| 706 | */ |
---|
| 707 | static int read_eeprom(unsigned long ioaddr, int location, int addr_len) |
---|
| 708 | { |
---|
| 709 | int i; |
---|
| 710 | unsigned short retval = 0; |
---|
| 711 | long ee_addr = ioaddr + CSR9; |
---|
| 712 | int read_cmd = location | EE_READ_CMD; |
---|
| 713 | |
---|
| 714 | #ifdef TULIP_DEBUG_WHERE |
---|
| 715 | whereami("read_eeprom\n"); |
---|
| 716 | #endif |
---|
| 717 | |
---|
| 718 | outl(EE_ENB & ~EE_CS, ee_addr); |
---|
| 719 | outl(EE_ENB, ee_addr); |
---|
| 720 | |
---|
| 721 | /* Shift the read command bits out. */ |
---|
| 722 | for (i = 4 + addr_len; i >= 0; i--) { |
---|
| 723 | short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; |
---|
| 724 | outl(EE_ENB | dataval, ee_addr); |
---|
| 725 | eeprom_delay(); |
---|
| 726 | outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); |
---|
| 727 | eeprom_delay(); |
---|
| 728 | } |
---|
| 729 | outl(EE_ENB, ee_addr); |
---|
| 730 | |
---|
| 731 | for (i = 16; i > 0; i--) { |
---|
| 732 | outl(EE_ENB | EE_SHIFT_CLK, ee_addr); |
---|
| 733 | eeprom_delay(); |
---|
| 734 | retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); |
---|
| 735 | outl(EE_ENB, ee_addr); |
---|
| 736 | eeprom_delay(); |
---|
| 737 | } |
---|
| 738 | |
---|
| 739 | /* Terminate the EEPROM access. */ |
---|
| 740 | outl(EE_ENB & ~EE_CS, ee_addr); |
---|
| 741 | return retval; |
---|
| 742 | } |
---|
| 743 | |
---|
| 744 | |
---|
| 745 | /*********************************************************************/ |
---|
| 746 | /* EEPROM Parsing Code */ |
---|
| 747 | /*********************************************************************/ |
---|
| 748 | static void parse_eeprom(struct nic *nic) |
---|
| 749 | { |
---|
| 750 | unsigned char *p, *ee_data = tp->eeprom; |
---|
| 751 | int new_advertise = 0; |
---|
| 752 | int i; |
---|
| 753 | |
---|
| 754 | #ifdef TULIP_DEBUG_WHERE |
---|
| 755 | whereami("parse_eeprom\n"); |
---|
| 756 | #endif |
---|
| 757 | |
---|
| 758 | tp->mtable = 0; |
---|
| 759 | /* Detect an old-style (SA only) EEPROM layout: |
---|
| 760 | memcmp(ee_data, ee_data+16, 8). */ |
---|
| 761 | for (i = 0; i < 8; i ++) |
---|
| 762 | if (ee_data[i] != ee_data[16+i]) |
---|
| 763 | break; |
---|
| 764 | if (i >= 8) { |
---|
| 765 | /* Do a fix-up based on the vendor half of the station address. */ |
---|
| 766 | for (i = 0; eeprom_fixups[i].name; i++) { |
---|
| 767 | if (nic->node_addr[0] == eeprom_fixups[i].addr0 |
---|
| 768 | && nic->node_addr[1] == eeprom_fixups[i].addr1 |
---|
| 769 | && nic->node_addr[2] == eeprom_fixups[i].addr2) { |
---|
| 770 | if (nic->node_addr[2] == 0xE8 && ee_data[0x1a] == 0x55) |
---|
| 771 | i++; /* An Accton EN1207, not an outlaw Maxtech. */ |
---|
| 772 | memcpy(ee_data + 26, eeprom_fixups[i].newtable, |
---|
| 773 | sizeof(eeprom_fixups[i].newtable)); |
---|
| 774 | #ifdef TULIP_DEBUG |
---|
| 775 | printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n", |
---|
| 776 | tp->nic_name, eeprom_fixups[i].name, tp->nic_name); |
---|
| 777 | #endif |
---|
| 778 | break; |
---|
| 779 | } |
---|
| 780 | } |
---|
| 781 | if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ |
---|
| 782 | #ifdef TULIP_DEBUG |
---|
| 783 | printf("%s: Old style EEPROM with no media selection information.\n", |
---|
| 784 | tp->nic_name); |
---|
| 785 | #endif |
---|
| 786 | return; |
---|
| 787 | } |
---|
| 788 | } |
---|
| 789 | |
---|
| 790 | if (ee_data[19] > 1) { |
---|
| 791 | #ifdef TULIP_DEBUG |
---|
| 792 | printf("%s: Multiport cards (%d ports) may not work correctly.\n", |
---|
| 793 | tp->nic_name, ee_data[19]); |
---|
| 794 | #endif |
---|
| 795 | } |
---|
| 796 | |
---|
| 797 | p = (void *)ee_data + ee_data[27]; |
---|
| 798 | |
---|
| 799 | if (ee_data[27] == 0) { /* No valid media table. */ |
---|
| 800 | #ifdef TULIP_DEBUG |
---|
| 801 | if (tulip_debug > 1) { |
---|
| 802 | printf("%s: No Valid Media Table. ee_data[27] = %hhX\n", |
---|
| 803 | tp->nic_name, ee_data[27]); |
---|
| 804 | } |
---|
| 805 | #endif |
---|
| 806 | } else if (tp->chip_id == DC21041) { |
---|
| 807 | int media = get_u16(p); |
---|
| 808 | int count = p[2]; |
---|
| 809 | p += 3; |
---|
| 810 | |
---|
| 811 | printf("%s: 21041 Media table, default media %hX (%s).\n", |
---|
| 812 | tp->nic_name, media, |
---|
| 813 | media & 0x0800 ? "Autosense" : medianame[media & 15]); |
---|
| 814 | for (i = 0; i < count; i++) { |
---|
| 815 | unsigned char media_block = *p++; |
---|
| 816 | int media_code = media_block & MEDIA_MASK; |
---|
| 817 | if (media_block & 0x40) |
---|
| 818 | p += 6; |
---|
| 819 | switch(media_code) { |
---|
| 820 | case 0: new_advertise |= 0x0020; break; |
---|
| 821 | case 4: new_advertise |= 0x0040; break; |
---|
| 822 | } |
---|
| 823 | printf("%s: 21041 media #%d, %s.\n", |
---|
| 824 | tp->nic_name, media_code, medianame[media_code]); |
---|
| 825 | } |
---|
| 826 | } else { |
---|
| 827 | unsigned char csr12dir = 0; |
---|
| 828 | int count; |
---|
| 829 | struct mediatable *mtable; |
---|
| 830 | u16 media = get_u16(p); |
---|
| 831 | |
---|
| 832 | p += 2; |
---|
| 833 | if (tp->flags & CSR12_IN_SROM) |
---|
| 834 | csr12dir = *p++; |
---|
| 835 | count = *p++; |
---|
| 836 | |
---|
| 837 | tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0]; |
---|
| 838 | |
---|
| 839 | mtable->defaultmedia = media; |
---|
| 840 | mtable->leafcount = count; |
---|
| 841 | mtable->csr12dir = csr12dir; |
---|
| 842 | mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; |
---|
| 843 | mtable->csr15dir = mtable->csr15val = 0; |
---|
| 844 | |
---|
| 845 | printf("%s: EEPROM default media type %s.\n", tp->nic_name, |
---|
| 846 | media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); |
---|
| 847 | |
---|
| 848 | for (i = 0; i < count; i++) { |
---|
| 849 | struct medialeaf *leaf = &mtable->mleaf[i]; |
---|
| 850 | |
---|
| 851 | if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */ |
---|
| 852 | leaf->type = 0; |
---|
| 853 | leaf->media = p[0] & 0x3f; |
---|
| 854 | leaf->leafdata = p; |
---|
| 855 | if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */ |
---|
| 856 | mtable->has_mii = 1; |
---|
| 857 | p += 4; |
---|
| 858 | } else { |
---|
| 859 | switch(leaf->type = p[1]) { |
---|
| 860 | case 5: |
---|
| 861 | mtable->has_reset = i; |
---|
| 862 | leaf->media = p[2] & 0x0f; |
---|
| 863 | break; |
---|
| 864 | case 1: case 3: |
---|
| 865 | mtable->has_mii = 1; |
---|
| 866 | leaf->media = 11; |
---|
| 867 | break; |
---|
| 868 | case 2: |
---|
| 869 | if ((p[2] & 0x3f) == 0) { |
---|
| 870 | u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008; |
---|
| 871 | u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3)); |
---|
| 872 | mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15; |
---|
| 873 | mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15; |
---|
| 874 | } |
---|
| 875 | /* Fall through. */ |
---|
| 876 | case 0: case 4: |
---|
| 877 | mtable->has_nonmii = 1; |
---|
| 878 | leaf->media = p[2] & MEDIA_MASK; |
---|
| 879 | switch (leaf->media) { |
---|
| 880 | case 0: new_advertise |= 0x0020; break; |
---|
| 881 | case 4: new_advertise |= 0x0040; break; |
---|
| 882 | case 3: new_advertise |= 0x0080; break; |
---|
| 883 | case 5: new_advertise |= 0x0100; break; |
---|
| 884 | case 6: new_advertise |= 0x0200; break; |
---|
| 885 | } |
---|
| 886 | break; |
---|
| 887 | default: |
---|
| 888 | leaf->media = 19; |
---|
| 889 | } |
---|
| 890 | leaf->leafdata = p + 2; |
---|
| 891 | p += (p[0] & 0x3f) + 1; |
---|
| 892 | } |
---|
| 893 | #ifdef TULIP_DEBUG |
---|
| 894 | if (tulip_debug > 1 && leaf->media == 11) { |
---|
| 895 | unsigned char *bp = leaf->leafdata; |
---|
| 896 | printf("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n", |
---|
| 897 | tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2], |
---|
| 898 | bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]); |
---|
| 899 | } |
---|
| 900 | #endif |
---|
| 901 | printf("%s: Index #%d - Media %s (#%d) described " |
---|
| 902 | "by a %s (%d) block.\n", |
---|
| 903 | tp->nic_name, i, medianame[leaf->media], leaf->media, |
---|
| 904 | leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN", |
---|
| 905 | leaf->type); |
---|
| 906 | } |
---|
| 907 | if (new_advertise) |
---|
| 908 | tp->sym_advertise = new_advertise; |
---|
| 909 | } |
---|
| 910 | } |
---|
| 911 | |
---|
| 912 | |
---|
| 913 | /*********************************************************************/ |
---|
| 914 | /* tulip_init_ring - setup the tx and rx descriptors */ |
---|
| 915 | /*********************************************************************/ |
---|
| 916 | static void tulip_init_ring(struct nic *nic __unused) |
---|
| 917 | { |
---|
| 918 | int i; |
---|
| 919 | |
---|
| 920 | #ifdef TULIP_DEBUG_WHERE |
---|
| 921 | whereami("tulip_init_ring\n"); |
---|
| 922 | #endif |
---|
| 923 | |
---|
| 924 | tp->cur_rx = 0; |
---|
| 925 | |
---|
| 926 | for (i = 0; i < RX_RING_SIZE; i++) { |
---|
| 927 | rx_ring[i].status = cpu_to_le32(0x80000000); |
---|
| 928 | rx_ring[i].length = cpu_to_le32(BUFLEN); |
---|
| 929 | rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]); |
---|
| 930 | rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]); |
---|
| 931 | } |
---|
| 932 | /* Mark the last entry as wrapping the ring. */ |
---|
| 933 | rx_ring[i-1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN); |
---|
| 934 | rx_ring[i-1].buffer2 = virt_to_le32desc(&rx_ring[0]); |
---|
| 935 | |
---|
| 936 | /* We only use 1 transmit buffer, but we use 2 descriptors so |
---|
| 937 | transmit engines have somewhere to point to if they feel the need */ |
---|
| 938 | |
---|
| 939 | tx_ring[0].status = 0x00000000; |
---|
| 940 | tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]); |
---|
| 941 | tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]); |
---|
| 942 | |
---|
| 943 | /* this descriptor should never get used, since it will never be owned |
---|
| 944 | by the machine (status will always == 0) */ |
---|
| 945 | tx_ring[1].status = 0x00000000; |
---|
| 946 | tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]); |
---|
| 947 | tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]); |
---|
| 948 | |
---|
| 949 | /* Mark the last entry as wrapping the ring, though this should never happen */ |
---|
| 950 | tx_ring[1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN); |
---|
| 951 | } |
---|
| 952 | |
---|
| 953 | |
---|
| 954 | static void set_rx_mode(struct nic *nic __unused) { |
---|
| 955 | int csr6 = inl(ioaddr + CSR6) & ~0x00D5; |
---|
| 956 | |
---|
| 957 | tp->csr6 &= ~0x00D5; |
---|
| 958 | |
---|
| 959 | /* !IFF_PROMISC */ |
---|
| 960 | tp->csr6 |= AcceptAllMulticast; |
---|
| 961 | csr6 |= AcceptAllMulticast; |
---|
| 962 | |
---|
| 963 | outl(csr6, ioaddr + CSR6); |
---|
| 964 | |
---|
| 965 | |
---|
| 966 | |
---|
| 967 | } |
---|
| 968 | |
---|
| 969 | /*********************************************************************/ |
---|
| 970 | /* eth_reset - Reset adapter */ |
---|
| 971 | /*********************************************************************/ |
---|
| 972 | static void tulip_reset(struct nic *nic) |
---|
| 973 | { |
---|
| 974 | int i; |
---|
| 975 | unsigned long to; |
---|
| 976 | |
---|
| 977 | #ifdef TULIP_DEBUG_WHERE |
---|
| 978 | whereami("tulip_reset\n"); |
---|
| 979 | #endif |
---|
| 980 | |
---|
| 981 | /* Stop Tx and RX */ |
---|
| 982 | outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); |
---|
| 983 | |
---|
| 984 | /* On some chip revs we must set the MII/SYM port before the reset!? */ |
---|
| 985 | if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) { |
---|
| 986 | outl(0x814C0000, ioaddr + CSR6); |
---|
| 987 | } |
---|
| 988 | |
---|
| 989 | /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ |
---|
| 990 | outl(0x00000001, ioaddr + CSR0); |
---|
| 991 | tulip_wait(1); |
---|
| 992 | |
---|
| 993 | /* turn off reset and set cache align=16lword, burst=unlimit */ |
---|
| 994 | outl(tp->csr0, ioaddr + CSR0); |
---|
| 995 | |
---|
| 996 | /* Wait the specified 50 PCI cycles after a reset */ |
---|
| 997 | tulip_wait(1); |
---|
| 998 | |
---|
| 999 | /* set up transmit and receive descriptors */ |
---|
| 1000 | tulip_init_ring(nic); |
---|
| 1001 | |
---|
| 1002 | if (tp->chip_id == PNIC2) { |
---|
| 1003 | u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0); |
---|
| 1004 | /* This address setting does not appear to impact chip operation?? */ |
---|
| 1005 | outl((nic->node_addr[5]<<8) + nic->node_addr[4] + |
---|
| 1006 | (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16), |
---|
| 1007 | ioaddr + 0xB0); |
---|
| 1008 | outl(addr_high + (addr_high<<16), ioaddr + 0xB8); |
---|
| 1009 | } |
---|
| 1010 | |
---|
| 1011 | /* MC_HASH_ONLY boards don't support setup packets */ |
---|
| 1012 | if (tp->flags & MC_HASH_ONLY) { |
---|
| 1013 | u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr)); |
---|
| 1014 | u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4))); |
---|
| 1015 | |
---|
| 1016 | /* clear multicast hash filters and setup MAC address filters */ |
---|
| 1017 | if (tp->flags & IS_ASIX) { |
---|
| 1018 | outl(0, ioaddr + CSR13); |
---|
| 1019 | outl(addr_low, ioaddr + CSR14); |
---|
| 1020 | outl(1, ioaddr + CSR13); |
---|
| 1021 | outl(addr_high, ioaddr + CSR14); |
---|
| 1022 | outl(2, ioaddr + CSR13); |
---|
| 1023 | outl(0, ioaddr + CSR14); |
---|
| 1024 | outl(3, ioaddr + CSR13); |
---|
| 1025 | outl(0, ioaddr + CSR14); |
---|
| 1026 | } else if (tp->chip_id == COMET) { |
---|
| 1027 | outl(addr_low, ioaddr + 0xA4); |
---|
| 1028 | outl(addr_high, ioaddr + 0xA8); |
---|
| 1029 | outl(0, ioaddr + 0xAC); |
---|
| 1030 | outl(0, ioaddr + 0xB0); |
---|
| 1031 | } |
---|
| 1032 | } else { |
---|
| 1033 | /* for other boards we send a setup packet to initialize |
---|
| 1034 | the filters */ |
---|
| 1035 | u32 tx_flags = 0x08000000 | 192; |
---|
| 1036 | |
---|
| 1037 | /* construct perfect filter frame with mac address as first match |
---|
| 1038 | and broadcast address for all others */ |
---|
| 1039 | for (i=0; i<192; i++) |
---|
| 1040 | txb[i] = 0xFF; |
---|
| 1041 | txb[0] = nic->node_addr[0]; |
---|
| 1042 | txb[1] = nic->node_addr[1]; |
---|
| 1043 | txb[4] = nic->node_addr[2]; |
---|
| 1044 | txb[5] = nic->node_addr[3]; |
---|
| 1045 | txb[8] = nic->node_addr[4]; |
---|
| 1046 | txb[9] = nic->node_addr[5]; |
---|
| 1047 | |
---|
| 1048 | tx_ring[0].length = cpu_to_le32(tx_flags); |
---|
| 1049 | tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]); |
---|
| 1050 | tx_ring[0].status = cpu_to_le32(0x80000000); |
---|
| 1051 | } |
---|
| 1052 | |
---|
| 1053 | /* Point to rx and tx descriptors */ |
---|
| 1054 | outl(virt_to_le32desc(&rx_ring[0]), ioaddr + CSR3); |
---|
| 1055 | outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4); |
---|
| 1056 | |
---|
| 1057 | init_media(nic); |
---|
| 1058 | |
---|
| 1059 | /* set the chip's operating mode (but don't turn on xmit and recv yet) */ |
---|
| 1060 | outl((tp->csr6 & ~0x00002002), ioaddr + CSR6); |
---|
| 1061 | |
---|
| 1062 | /* send setup packet for cards that support it */ |
---|
| 1063 | if (!(tp->flags & MC_HASH_ONLY)) { |
---|
| 1064 | /* enable transmit wait for completion */ |
---|
| 1065 | outl(tp->csr6 | 0x00002000, ioaddr + CSR6); |
---|
| 1066 | /* immediate transmit demand */ |
---|
| 1067 | outl(0, ioaddr + CSR1); |
---|
| 1068 | |
---|
| 1069 | to = currticks() + TX_TIME_OUT; |
---|
| 1070 | while ((tx_ring[0].status & 0x80000000) && (currticks() < to)) |
---|
| 1071 | /* wait */ ; |
---|
| 1072 | |
---|
| 1073 | if (currticks() >= to) { |
---|
| 1074 | printf ("%s: TX Setup Timeout.\n", tp->nic_name); |
---|
| 1075 | } |
---|
| 1076 | } |
---|
| 1077 | |
---|
| 1078 | if (tp->chip_id == LC82C168) |
---|
| 1079 | tulip_check_duplex(nic); |
---|
| 1080 | |
---|
| 1081 | set_rx_mode(nic); |
---|
| 1082 | |
---|
| 1083 | /* enable transmit and receive */ |
---|
| 1084 | outl(tp->csr6 | 0x00002002, ioaddr + CSR6); |
---|
| 1085 | } |
---|
| 1086 | |
---|
| 1087 | |
---|
| 1088 | /*********************************************************************/ |
---|
| 1089 | /* eth_transmit - Transmit a frame */ |
---|
| 1090 | /*********************************************************************/ |
---|
| 1091 | static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, |
---|
| 1092 | unsigned int s, const char *p) |
---|
| 1093 | { |
---|
| 1094 | u16 nstype; |
---|
| 1095 | u32 to; |
---|
| 1096 | u32 csr6 = inl(ioaddr + CSR6); |
---|
| 1097 | |
---|
| 1098 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1099 | whereami("tulip_transmit\n"); |
---|
| 1100 | #endif |
---|
| 1101 | |
---|
| 1102 | /* Disable Tx */ |
---|
| 1103 | outl(csr6 & ~0x00002000, ioaddr + CSR6); |
---|
| 1104 | |
---|
| 1105 | memcpy(txb, d, ETH_ALEN); |
---|
| 1106 | memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); |
---|
| 1107 | nstype = htons((u16) t); |
---|
| 1108 | memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2); |
---|
| 1109 | memcpy(txb + ETH_HLEN, p, s); |
---|
| 1110 | |
---|
| 1111 | s += ETH_HLEN; |
---|
| 1112 | s &= 0x0FFF; |
---|
| 1113 | |
---|
| 1114 | /* pad to minimum packet size */ |
---|
| 1115 | while (s < ETH_ZLEN) |
---|
| 1116 | txb[s++] = '\0'; |
---|
| 1117 | |
---|
| 1118 | #ifdef TULIP_DEBUG |
---|
| 1119 | if (tulip_debug > 1) |
---|
| 1120 | printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t); |
---|
| 1121 | #endif |
---|
| 1122 | |
---|
| 1123 | /* setup the transmit descriptor */ |
---|
| 1124 | /* 0x60000000 = no interrupt on completion */ |
---|
| 1125 | tx_ring[0].length = cpu_to_le32(0x60000000 | s); |
---|
| 1126 | tx_ring[0].status = cpu_to_le32(0x80000000); |
---|
| 1127 | |
---|
| 1128 | /* Point to transmit descriptor */ |
---|
| 1129 | outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4); |
---|
| 1130 | |
---|
| 1131 | /* Enable Tx */ |
---|
| 1132 | outl(csr6 | 0x00002000, ioaddr + CSR6); |
---|
| 1133 | /* immediate transmit demand */ |
---|
| 1134 | outl(0, ioaddr + CSR1); |
---|
| 1135 | |
---|
| 1136 | to = currticks() + TX_TIME_OUT; |
---|
| 1137 | while ((tx_ring[0].status & 0x80000000) && (currticks() < to)) |
---|
| 1138 | /* wait */ ; |
---|
| 1139 | |
---|
| 1140 | if (currticks() >= to) { |
---|
| 1141 | printf ("TX Timeout!\n"); |
---|
| 1142 | } |
---|
| 1143 | |
---|
| 1144 | /* Disable Tx */ |
---|
| 1145 | outl(csr6 & ~0x00002000, ioaddr + CSR6); |
---|
| 1146 | } |
---|
| 1147 | |
---|
| 1148 | /*********************************************************************/ |
---|
| 1149 | /* eth_poll - Wait for a frame */ |
---|
| 1150 | /*********************************************************************/ |
---|
| 1151 | static int tulip_poll(struct nic *nic, int retrieve) |
---|
| 1152 | { |
---|
| 1153 | |
---|
| 1154 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1155 | whereami("tulip_poll\n"); |
---|
| 1156 | #endif |
---|
| 1157 | |
---|
| 1158 | /* no packet waiting. packet still owned by NIC */ |
---|
| 1159 | if (rx_ring[tp->cur_rx].status & 0x80000000) |
---|
| 1160 | return 0; |
---|
| 1161 | |
---|
| 1162 | if ( ! retrieve ) return 1; |
---|
| 1163 | |
---|
| 1164 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1165 | whereami("tulip_poll got one\n"); |
---|
| 1166 | #endif |
---|
| 1167 | |
---|
| 1168 | nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16; |
---|
| 1169 | |
---|
| 1170 | /* if we get a corrupted packet. throw it away and move on */ |
---|
| 1171 | if (rx_ring[tp->cur_rx].status & 0x00008000) { |
---|
| 1172 | /* return the descriptor and buffer to receive ring */ |
---|
| 1173 | rx_ring[tp->cur_rx].status = 0x80000000; |
---|
| 1174 | tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE; |
---|
| 1175 | return 0; |
---|
| 1176 | } |
---|
| 1177 | |
---|
| 1178 | /* copy packet to working buffer */ |
---|
| 1179 | memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen); |
---|
| 1180 | |
---|
| 1181 | /* return the descriptor and buffer to receive ring */ |
---|
| 1182 | rx_ring[tp->cur_rx].status = 0x80000000; |
---|
| 1183 | tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE; |
---|
| 1184 | |
---|
| 1185 | return 1; |
---|
| 1186 | } |
---|
| 1187 | |
---|
| 1188 | /*********************************************************************/ |
---|
| 1189 | /* eth_disable - Disable the interface */ |
---|
| 1190 | /*********************************************************************/ |
---|
| 1191 | static void tulip_disable ( struct nic *nic ) { |
---|
| 1192 | |
---|
| 1193 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1194 | whereami("tulip_disable\n"); |
---|
| 1195 | #endif |
---|
| 1196 | |
---|
| 1197 | tulip_reset(nic); |
---|
| 1198 | |
---|
| 1199 | /* disable interrupts */ |
---|
| 1200 | outl(0x00000000, ioaddr + CSR7); |
---|
| 1201 | |
---|
| 1202 | /* Stop the chip's Tx and Rx processes. */ |
---|
| 1203 | outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); |
---|
| 1204 | |
---|
| 1205 | /* Clear the missed-packet counter. */ |
---|
| 1206 | inl(ioaddr + CSR8); |
---|
| 1207 | } |
---|
| 1208 | |
---|
| 1209 | /*********************************************************************/ |
---|
| 1210 | /*IRQ - Enable, Disable, or Force interrupts */ |
---|
| 1211 | /*********************************************************************/ |
---|
| 1212 | static void tulip_irq(struct nic *nic __unused, irq_action_t action __unused) |
---|
| 1213 | { |
---|
| 1214 | switch ( action ) { |
---|
| 1215 | case DISABLE : |
---|
| 1216 | break; |
---|
| 1217 | case ENABLE : |
---|
| 1218 | break; |
---|
| 1219 | case FORCE : |
---|
| 1220 | break; |
---|
| 1221 | } |
---|
| 1222 | } |
---|
| 1223 | |
---|
| 1224 | static struct nic_operations tulip_operations = { |
---|
| 1225 | .connect = dummy_connect, |
---|
| 1226 | .poll = tulip_poll, |
---|
| 1227 | .transmit = tulip_transmit, |
---|
| 1228 | .irq = tulip_irq, |
---|
| 1229 | |
---|
| 1230 | }; |
---|
| 1231 | |
---|
| 1232 | /*********************************************************************/ |
---|
| 1233 | /* eth_probe - Look for an adapter */ |
---|
| 1234 | /*********************************************************************/ |
---|
| 1235 | static int tulip_probe ( struct nic *nic, struct pci_device *pci ) { |
---|
| 1236 | |
---|
| 1237 | u32 i; |
---|
| 1238 | u8 chip_rev; |
---|
| 1239 | u8 ee_data[EEPROM_SIZE]; |
---|
| 1240 | unsigned short sum; |
---|
| 1241 | int chip_idx; |
---|
| 1242 | static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'}; |
---|
| 1243 | |
---|
| 1244 | if (pci->ioaddr == 0) |
---|
| 1245 | return 0; |
---|
| 1246 | |
---|
| 1247 | ioaddr = pci->ioaddr; |
---|
| 1248 | nic->ioaddr = pci->ioaddr & ~3; |
---|
| 1249 | nic->irqno = 0; |
---|
| 1250 | |
---|
| 1251 | /* point to private storage */ |
---|
| 1252 | tp = &tulip_bss.tpx; |
---|
| 1253 | |
---|
| 1254 | tp->vendor_id = pci->vendor; |
---|
| 1255 | tp->dev_id = pci->device; |
---|
| 1256 | tp->nic_name = pci->driver_name; |
---|
| 1257 | |
---|
| 1258 | tp->if_port = 0; |
---|
| 1259 | tp->default_port = 0; |
---|
| 1260 | |
---|
| 1261 | adjust_pci_device(pci); |
---|
| 1262 | |
---|
| 1263 | /* disable interrupts */ |
---|
| 1264 | outl(0x00000000, ioaddr + CSR7); |
---|
| 1265 | |
---|
| 1266 | /* Stop the chip's Tx and Rx processes. */ |
---|
| 1267 | outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); |
---|
| 1268 | |
---|
| 1269 | /* Clear the missed-packet counter. */ |
---|
| 1270 | inl(ioaddr + CSR8); |
---|
| 1271 | |
---|
| 1272 | printf("\n"); /* so we start on a fresh line */ |
---|
| 1273 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1274 | whereami("tulip_probe\n"); |
---|
| 1275 | #endif |
---|
| 1276 | |
---|
| 1277 | #ifdef TULIP_DEBUG |
---|
| 1278 | if (tulip_debug > 1) |
---|
| 1279 | printf ("%s: Looking for Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name, |
---|
| 1280 | tp->vendor, tp->dev_id); |
---|
| 1281 | #endif |
---|
| 1282 | |
---|
| 1283 | /* Figure out which chip we're dealing with */ |
---|
| 1284 | i = 0; |
---|
| 1285 | chip_idx = -1; |
---|
| 1286 | |
---|
| 1287 | while (pci_id_tbl[i].name) { |
---|
| 1288 | if ( (((u32) tp->dev_id << 16) | tp->vendor_id) == |
---|
| 1289 | (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) { |
---|
| 1290 | chip_idx = pci_id_tbl[i].drv_flags; |
---|
| 1291 | break; |
---|
| 1292 | } |
---|
| 1293 | i++; |
---|
| 1294 | } |
---|
| 1295 | |
---|
| 1296 | if (chip_idx == -1) { |
---|
| 1297 | printf ("%s: Unknown Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name, |
---|
| 1298 | tp->vendor_id, tp->dev_id); |
---|
| 1299 | return 0; |
---|
| 1300 | } |
---|
| 1301 | |
---|
| 1302 | tp->pci_id_idx = i; |
---|
| 1303 | tp->flags = tulip_tbl[chip_idx].flags; |
---|
| 1304 | |
---|
| 1305 | #ifdef TULIP_DEBUG |
---|
| 1306 | if (tulip_debug > 1) { |
---|
| 1307 | printf ("%s: tp->pci_id_idx == %d, name == %s\n", tp->nic_name, |
---|
| 1308 | tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name); |
---|
| 1309 | printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx, |
---|
| 1310 | tulip_tbl[chip_idx].chip_name); |
---|
| 1311 | } |
---|
| 1312 | #endif |
---|
| 1313 | |
---|
| 1314 | /* Bring the 21041/21143 out of sleep mode. |
---|
| 1315 | Caution: Snooze mode does not work with some boards! */ |
---|
| 1316 | if (tp->flags & HAS_PWRDWN) |
---|
| 1317 | pci_write_config_dword(pci, 0x40, 0x00000000); |
---|
| 1318 | |
---|
| 1319 | if (inl(ioaddr + CSR5) == 0xFFFFFFFF) { |
---|
| 1320 | printf("%s: The Tulip chip at %X is not functioning.\n", |
---|
| 1321 | tp->nic_name, (unsigned int) ioaddr); |
---|
| 1322 | return 0; |
---|
| 1323 | } |
---|
| 1324 | |
---|
| 1325 | pci_read_config_byte(pci, PCI_REVISION, &chip_rev); |
---|
| 1326 | |
---|
| 1327 | printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name, |
---|
| 1328 | tulip_tbl[chip_idx].chip_name, chip_rev, (unsigned int) ioaddr); |
---|
| 1329 | printf("%s: Vendor=%hX Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id); |
---|
| 1330 | |
---|
| 1331 | if (chip_idx == DC21041 && inl(ioaddr + CSR9) & 0x8000) { |
---|
| 1332 | printf(" 21040 compatible mode."); |
---|
| 1333 | chip_idx = DC21040; |
---|
| 1334 | } |
---|
| 1335 | |
---|
| 1336 | printf("\n"); |
---|
| 1337 | |
---|
| 1338 | /* The SROM/EEPROM interface varies dramatically. */ |
---|
| 1339 | sum = 0; |
---|
| 1340 | if (chip_idx == DC21040) { |
---|
| 1341 | outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */ |
---|
| 1342 | for (i = 0; i < ETH_ALEN; i++) { |
---|
| 1343 | int value, boguscnt = 100000; |
---|
| 1344 | do |
---|
| 1345 | value = inl(ioaddr + CSR9); |
---|
| 1346 | while (value < 0 && --boguscnt > 0); |
---|
| 1347 | nic->node_addr[i] = value; |
---|
| 1348 | sum += value & 0xff; |
---|
| 1349 | } |
---|
| 1350 | } else if (chip_idx == LC82C168) { |
---|
| 1351 | for (i = 0; i < 3; i++) { |
---|
| 1352 | int value, boguscnt = 100000; |
---|
| 1353 | outl(0x600 | i, ioaddr + 0x98); |
---|
| 1354 | do |
---|
| 1355 | value = inl(ioaddr + CSR9); |
---|
| 1356 | while (value < 0 && --boguscnt > 0); |
---|
| 1357 | put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i); |
---|
| 1358 | sum += value & 0xffff; |
---|
| 1359 | } |
---|
| 1360 | } else if (chip_idx == COMET) { |
---|
| 1361 | /* No need to read the EEPROM. */ |
---|
| 1362 | put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr); |
---|
| 1363 | put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4)); |
---|
| 1364 | for (i = 0; i < ETH_ALEN; i ++) |
---|
| 1365 | sum += nic->node_addr[i]; |
---|
| 1366 | } else { |
---|
| 1367 | /* A serial EEPROM interface, we read now and sort it out later. */ |
---|
| 1368 | int sa_offset = 0; |
---|
| 1369 | int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; |
---|
| 1370 | |
---|
| 1371 | for (i = 0; i < sizeof(ee_data)/2; i++) |
---|
| 1372 | ((u16 *)ee_data)[i] = |
---|
| 1373 | le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size)); |
---|
| 1374 | |
---|
| 1375 | /* DEC now has a specification (see Notes) but early board makers |
---|
| 1376 | just put the address in the first EEPROM locations. */ |
---|
| 1377 | /* This does memcmp(eedata, eedata+16, 8) */ |
---|
| 1378 | for (i = 0; i < 8; i ++) |
---|
| 1379 | if (ee_data[i] != ee_data[16+i]) |
---|
| 1380 | sa_offset = 20; |
---|
| 1381 | if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) { |
---|
| 1382 | sa_offset = 2; /* Grrr, damn Matrox boards. */ |
---|
| 1383 | } |
---|
| 1384 | for (i = 0; i < ETH_ALEN; i ++) { |
---|
| 1385 | nic->node_addr[i] = ee_data[i + sa_offset]; |
---|
| 1386 | sum += ee_data[i + sa_offset]; |
---|
| 1387 | } |
---|
| 1388 | } |
---|
| 1389 | /* Lite-On boards have the address byte-swapped. */ |
---|
| 1390 | if ((nic->node_addr[0] == 0xA0 || nic->node_addr[0] == 0xC0) |
---|
| 1391 | && nic->node_addr[1] == 0x00) |
---|
| 1392 | for (i = 0; i < ETH_ALEN; i+=2) { |
---|
| 1393 | char tmp = nic->node_addr[i]; |
---|
| 1394 | nic->node_addr[i] = nic->node_addr[i+1]; |
---|
| 1395 | nic->node_addr[i+1] = tmp; |
---|
| 1396 | } |
---|
| 1397 | |
---|
| 1398 | if (sum == 0 || sum == ETH_ALEN*0xff) { |
---|
| 1399 | printf("%s: EEPROM not present!\n", tp->nic_name); |
---|
| 1400 | for (i = 0; i < ETH_ALEN-1; i++) |
---|
| 1401 | nic->node_addr[i] = last_phys_addr[i]; |
---|
| 1402 | nic->node_addr[i] = last_phys_addr[i] + 1; |
---|
| 1403 | } |
---|
| 1404 | |
---|
| 1405 | for (i = 0; i < ETH_ALEN; i++) |
---|
| 1406 | last_phys_addr[i] = nic->node_addr[i]; |
---|
| 1407 | |
---|
| 1408 | DBG ( "%s: %s at ioaddr %hX\n", tp->nic_name, eth_ntoa ( nic->node_addr ), |
---|
| 1409 | (unsigned int) ioaddr ); |
---|
| 1410 | |
---|
| 1411 | tp->chip_id = chip_idx; |
---|
| 1412 | tp->revision = chip_rev; |
---|
| 1413 | tp->csr0 = csr0; |
---|
| 1414 | |
---|
| 1415 | /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. |
---|
| 1416 | And the ASIX must have a burst limit or horrible things happen. */ |
---|
| 1417 | if (chip_idx == DC21143 && chip_rev == 65) |
---|
| 1418 | tp->csr0 &= ~0x01000000; |
---|
| 1419 | else if (tp->flags & IS_ASIX) |
---|
| 1420 | tp->csr0 |= 0x2000; |
---|
| 1421 | |
---|
| 1422 | if (media_cap[tp->default_port] & MediaIsMII) { |
---|
| 1423 | static const u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, |
---|
| 1424 | 0x80, 0x100, 0x200 }; |
---|
| 1425 | tp->mii_advertise = media2advert[tp->default_port - 9]; |
---|
| 1426 | tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */ |
---|
| 1427 | } |
---|
| 1428 | |
---|
| 1429 | /* This is logically part of the probe routine, but too complex |
---|
| 1430 | to write inline. */ |
---|
| 1431 | if (tp->flags & HAS_MEDIA_TABLE) { |
---|
| 1432 | memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom)); |
---|
| 1433 | parse_eeprom(nic); |
---|
| 1434 | } |
---|
| 1435 | |
---|
| 1436 | start_link(nic); |
---|
| 1437 | |
---|
| 1438 | /* reset the device and make ready for tx and rx of packets */ |
---|
| 1439 | tulip_reset(nic); |
---|
| 1440 | nic->nic_op = &tulip_operations; |
---|
| 1441 | |
---|
| 1442 | /* give the board a chance to reset before returning */ |
---|
| 1443 | tulip_wait(4*TICKS_PER_SEC); |
---|
| 1444 | |
---|
| 1445 | return 1; |
---|
| 1446 | } |
---|
| 1447 | |
---|
| 1448 | static void start_link(struct nic *nic) |
---|
| 1449 | { |
---|
| 1450 | int i; |
---|
| 1451 | |
---|
| 1452 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1453 | whereami("start_link\n"); |
---|
| 1454 | #endif |
---|
| 1455 | |
---|
| 1456 | if ((tp->flags & ALWAYS_CHECK_MII) || |
---|
| 1457 | (tp->mtable && tp->mtable->has_mii) || |
---|
| 1458 | ( ! tp->mtable && (tp->flags & HAS_MII))) { |
---|
| 1459 | unsigned int phy, phy_idx; |
---|
| 1460 | if (tp->mtable && tp->mtable->has_mii) { |
---|
| 1461 | for (i = 0; i < tp->mtable->leafcount; i++) |
---|
| 1462 | if (tp->mtable->mleaf[i].media == 11) { |
---|
| 1463 | tp->cur_index = i; |
---|
| 1464 | tp->saved_if_port = tp->if_port; |
---|
| 1465 | select_media(nic, 2); |
---|
| 1466 | tp->if_port = tp->saved_if_port; |
---|
| 1467 | break; |
---|
| 1468 | } |
---|
| 1469 | } |
---|
| 1470 | |
---|
| 1471 | /* Find the connected MII xcvrs. */ |
---|
| 1472 | for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); |
---|
| 1473 | phy++) { |
---|
| 1474 | int mii_status = mdio_read(nic, phy, 1); |
---|
| 1475 | if ((mii_status & 0x8301) == 0x8001 || |
---|
| 1476 | ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) { |
---|
| 1477 | int mii_reg0 = mdio_read(nic, phy, 0); |
---|
| 1478 | int mii_advert = mdio_read(nic, phy, 4); |
---|
| 1479 | int to_advert; |
---|
| 1480 | |
---|
| 1481 | if (tp->mii_advertise) |
---|
| 1482 | to_advert = tp->mii_advertise; |
---|
| 1483 | else if (tp->advertising[phy_idx]) |
---|
| 1484 | to_advert = tp->advertising[phy_idx]; |
---|
| 1485 | else /* Leave unchanged. */ |
---|
| 1486 | tp->mii_advertise = to_advert = mii_advert; |
---|
| 1487 | |
---|
| 1488 | tp->phys[phy_idx++] = phy; |
---|
| 1489 | printf("%s: MII transceiver %d config %hX status %hX advertising %hX.\n", |
---|
| 1490 | tp->nic_name, phy, mii_reg0, mii_status, mii_advert); |
---|
| 1491 | /* Fixup for DLink with miswired PHY. */ |
---|
| 1492 | if (mii_advert != to_advert) { |
---|
| 1493 | printf("%s: Advertising %hX on PHY %d previously advertising %hX.\n", |
---|
| 1494 | tp->nic_name, to_advert, phy, mii_advert); |
---|
| 1495 | mdio_write(nic, phy, 4, to_advert); |
---|
| 1496 | } |
---|
| 1497 | /* Enable autonegotiation: some boards default to off. */ |
---|
| 1498 | mdio_write(nic, phy, 0, mii_reg0 | |
---|
| 1499 | (tp->full_duplex ? 0x1100 : 0x1000) | |
---|
| 1500 | (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0)); |
---|
| 1501 | } |
---|
| 1502 | } |
---|
| 1503 | tp->mii_cnt = phy_idx; |
---|
| 1504 | if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) { |
---|
| 1505 | printf("%s: ***WARNING***: No MII transceiver found!\n", |
---|
| 1506 | tp->nic_name); |
---|
| 1507 | tp->phys[0] = 1; |
---|
| 1508 | } |
---|
| 1509 | } |
---|
| 1510 | |
---|
| 1511 | /* Reset the xcvr interface and turn on heartbeat. */ |
---|
| 1512 | switch (tp->chip_id) { |
---|
| 1513 | case DC21040: |
---|
| 1514 | outl(0x00000000, ioaddr + CSR13); |
---|
| 1515 | outl(0x00000004, ioaddr + CSR13); |
---|
| 1516 | break; |
---|
| 1517 | case DC21041: |
---|
| 1518 | /* This is nway_start(). */ |
---|
| 1519 | if (tp->sym_advertise == 0) |
---|
| 1520 | tp->sym_advertise = 0x0061; |
---|
| 1521 | outl(0x00000000, ioaddr + CSR13); |
---|
| 1522 | outl(0xFFFFFFFF, ioaddr + CSR14); |
---|
| 1523 | outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ |
---|
| 1524 | outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6); |
---|
| 1525 | outl(0x0000EF01, ioaddr + CSR13); |
---|
| 1526 | break; |
---|
| 1527 | case DC21140: default: |
---|
| 1528 | if (tp->mtable) |
---|
| 1529 | outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); |
---|
| 1530 | break; |
---|
| 1531 | case DC21142: |
---|
| 1532 | case PNIC2: |
---|
| 1533 | if (tp->mii_cnt || media_cap[tp->if_port] & MediaIsMII) { |
---|
| 1534 | outl(0x82020000, ioaddr + CSR6); |
---|
| 1535 | outl(0x0000, ioaddr + CSR13); |
---|
| 1536 | outl(0x0000, ioaddr + CSR14); |
---|
| 1537 | outl(0x820E0000, ioaddr + CSR6); |
---|
| 1538 | } else |
---|
| 1539 | nway_start(nic); |
---|
| 1540 | break; |
---|
| 1541 | case LC82C168: |
---|
| 1542 | if ( ! tp->mii_cnt) { |
---|
| 1543 | tp->nway = 1; |
---|
| 1544 | tp->nwayset = 0; |
---|
| 1545 | outl(0x00420000, ioaddr + CSR6); |
---|
| 1546 | outl(0x30, ioaddr + CSR12); |
---|
| 1547 | outl(0x0001F078, ioaddr + 0xB8); |
---|
| 1548 | outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ |
---|
| 1549 | } |
---|
| 1550 | break; |
---|
| 1551 | case MX98713: case COMPEX9881: |
---|
| 1552 | outl(0x00000000, ioaddr + CSR6); |
---|
| 1553 | outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ |
---|
| 1554 | outl(0x00000001, ioaddr + CSR13); |
---|
| 1555 | break; |
---|
| 1556 | case MX98715: case MX98725: |
---|
| 1557 | outl(0x01a80000, ioaddr + CSR6); |
---|
| 1558 | outl(0xFFFFFFFF, ioaddr + CSR14); |
---|
| 1559 | outl(0x00001000, ioaddr + CSR12); |
---|
| 1560 | break; |
---|
| 1561 | case COMET: |
---|
| 1562 | /* No initialization necessary. */ |
---|
| 1563 | break; |
---|
| 1564 | } |
---|
| 1565 | } |
---|
| 1566 | |
---|
| 1567 | static void nway_start(struct nic *nic __unused) |
---|
| 1568 | { |
---|
| 1569 | int csr14 = ((tp->sym_advertise & 0x0780) << 9) | |
---|
| 1570 | ((tp->sym_advertise&0x0020)<<1) | 0xffbf; |
---|
| 1571 | |
---|
| 1572 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1573 | whereami("nway_start\n"); |
---|
| 1574 | #endif |
---|
| 1575 | |
---|
| 1576 | tp->if_port = 0; |
---|
| 1577 | tp->nway = tp->mediasense = 1; |
---|
| 1578 | tp->nwayset = tp->lpar = 0; |
---|
| 1579 | if (tp->chip_id == PNIC2) { |
---|
| 1580 | tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0); |
---|
| 1581 | return; |
---|
| 1582 | } |
---|
| 1583 | #ifdef TULIP_DEBUG |
---|
| 1584 | if (tulip_debug > 1) |
---|
| 1585 | printf("%s: Restarting internal NWay autonegotiation, %X.\n", |
---|
| 1586 | tp->nic_name, csr14); |
---|
| 1587 | #endif |
---|
| 1588 | outl(0x0001, ioaddr + CSR13); |
---|
| 1589 | outl(csr14, ioaddr + CSR14); |
---|
| 1590 | tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0); |
---|
| 1591 | outl(tp->csr6, ioaddr + CSR6); |
---|
| 1592 | if (tp->mtable && tp->mtable->csr15dir) { |
---|
| 1593 | outl(tp->mtable->csr15dir, ioaddr + CSR15); |
---|
| 1594 | outl(tp->mtable->csr15val, ioaddr + CSR15); |
---|
| 1595 | } else if (tp->chip_id != PNIC2) |
---|
| 1596 | outw(0x0008, ioaddr + CSR15); |
---|
| 1597 | if (tp->chip_id == DC21041) /* Trigger NWAY. */ |
---|
| 1598 | outl(0xEF01, ioaddr + CSR12); |
---|
| 1599 | else |
---|
| 1600 | outl(0x1301, ioaddr + CSR12); |
---|
| 1601 | } |
---|
| 1602 | |
---|
| 1603 | static void init_media(struct nic *nic) |
---|
| 1604 | { |
---|
| 1605 | int i; |
---|
| 1606 | |
---|
| 1607 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1608 | whereami("init_media\n"); |
---|
| 1609 | #endif |
---|
| 1610 | |
---|
| 1611 | tp->saved_if_port = tp->if_port; |
---|
| 1612 | if (tp->if_port == 0) |
---|
| 1613 | tp->if_port = tp->default_port; |
---|
| 1614 | |
---|
| 1615 | /* Allow selecting a default media. */ |
---|
| 1616 | i = 0; |
---|
| 1617 | if (tp->mtable == NULL) |
---|
| 1618 | goto media_picked; |
---|
| 1619 | if (tp->if_port) { |
---|
| 1620 | int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 : |
---|
| 1621 | (tp->if_port == 12 ? 0 : tp->if_port); |
---|
| 1622 | for (i = 0; i < tp->mtable->leafcount; i++) |
---|
| 1623 | if (tp->mtable->mleaf[i].media == looking_for) { |
---|
| 1624 | printf("%s: Using user-specified media %s.\n", |
---|
| 1625 | tp->nic_name, medianame[tp->if_port]); |
---|
| 1626 | goto media_picked; |
---|
| 1627 | } |
---|
| 1628 | } |
---|
| 1629 | if ((tp->mtable->defaultmedia & 0x0800) == 0) { |
---|
| 1630 | int looking_for = tp->mtable->defaultmedia & 15; |
---|
| 1631 | for (i = 0; i < tp->mtable->leafcount; i++) |
---|
| 1632 | if (tp->mtable->mleaf[i].media == looking_for) { |
---|
| 1633 | printf("%s: Using EEPROM-set media %s.\n", |
---|
| 1634 | tp->nic_name, medianame[looking_for]); |
---|
| 1635 | goto media_picked; |
---|
| 1636 | } |
---|
| 1637 | } |
---|
| 1638 | /* Start sensing first non-full-duplex media. */ |
---|
| 1639 | for (i = tp->mtable->leafcount - 1; |
---|
| 1640 | (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) |
---|
| 1641 | ; |
---|
| 1642 | media_picked: |
---|
| 1643 | |
---|
| 1644 | tp->csr6 = 0; |
---|
| 1645 | tp->cur_index = i; |
---|
| 1646 | tp->nwayset = 0; |
---|
| 1647 | |
---|
| 1648 | if (tp->if_port) { |
---|
| 1649 | if (tp->chip_id == DC21143 && media_cap[tp->if_port] & MediaIsMII) { |
---|
| 1650 | /* We must reset the media CSRs when we force-select MII mode. */ |
---|
| 1651 | outl(0x0000, ioaddr + CSR13); |
---|
| 1652 | outl(0x0000, ioaddr + CSR14); |
---|
| 1653 | outl(0x0008, ioaddr + CSR15); |
---|
| 1654 | } |
---|
| 1655 | select_media(nic, 1); |
---|
| 1656 | return; |
---|
| 1657 | } |
---|
| 1658 | switch(tp->chip_id) { |
---|
| 1659 | case DC21041: |
---|
| 1660 | /* tp->nway = 1;*/ |
---|
| 1661 | nway_start(nic); |
---|
| 1662 | break; |
---|
| 1663 | case DC21142: |
---|
| 1664 | if (tp->mii_cnt) { |
---|
| 1665 | select_media(nic, 1); |
---|
| 1666 | #ifdef TULIP_DEBUG |
---|
| 1667 | if (tulip_debug > 1) |
---|
| 1668 | printf("%s: Using MII transceiver %d, status %hX.\n", |
---|
| 1669 | tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1)); |
---|
| 1670 | #endif |
---|
| 1671 | outl(0x82020000, ioaddr + CSR6); |
---|
| 1672 | tp->csr6 = 0x820E0000; |
---|
| 1673 | tp->if_port = 11; |
---|
| 1674 | outl(0x0000, ioaddr + CSR13); |
---|
| 1675 | outl(0x0000, ioaddr + CSR14); |
---|
| 1676 | } else |
---|
| 1677 | nway_start(nic); |
---|
| 1678 | break; |
---|
| 1679 | case PNIC2: |
---|
| 1680 | nway_start(nic); |
---|
| 1681 | break; |
---|
| 1682 | case LC82C168: |
---|
| 1683 | if (tp->mii_cnt) { |
---|
| 1684 | tp->if_port = 11; |
---|
| 1685 | tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); |
---|
| 1686 | outl(0x0001, ioaddr + CSR15); |
---|
| 1687 | } else if (inl(ioaddr + CSR5) & TPLnkPass) |
---|
| 1688 | pnic_do_nway(nic); |
---|
| 1689 | else { |
---|
| 1690 | /* Start with 10mbps to do autonegotiation. */ |
---|
| 1691 | outl(0x32, ioaddr + CSR12); |
---|
| 1692 | tp->csr6 = 0x00420000; |
---|
| 1693 | outl(0x0001B078, ioaddr + 0xB8); |
---|
| 1694 | outl(0x0201B078, ioaddr + 0xB8); |
---|
| 1695 | } |
---|
| 1696 | break; |
---|
| 1697 | case MX98713: case COMPEX9881: |
---|
| 1698 | tp->if_port = 0; |
---|
| 1699 | tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); |
---|
| 1700 | outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); |
---|
| 1701 | break; |
---|
| 1702 | case MX98715: case MX98725: |
---|
| 1703 | /* Provided by BOLO, Macronix - 12/10/1998. */ |
---|
| 1704 | tp->if_port = 0; |
---|
| 1705 | tp->csr6 = 0x01a80200; |
---|
| 1706 | outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); |
---|
| 1707 | outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0); |
---|
| 1708 | break; |
---|
| 1709 | case COMET: |
---|
| 1710 | /* Enable automatic Tx underrun recovery */ |
---|
| 1711 | outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88); |
---|
| 1712 | tp->if_port = 0; |
---|
| 1713 | tp->csr6 = 0x00040000; |
---|
| 1714 | break; |
---|
| 1715 | case AX88140: case AX88141: |
---|
| 1716 | tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; |
---|
| 1717 | break; |
---|
| 1718 | default: |
---|
| 1719 | select_media(nic, 1); |
---|
| 1720 | } |
---|
| 1721 | } |
---|
| 1722 | |
---|
| 1723 | static void pnic_do_nway(struct nic *nic __unused) |
---|
| 1724 | { |
---|
| 1725 | u32 phy_reg = inl(ioaddr + 0xB8); |
---|
| 1726 | u32 new_csr6 = tp->csr6 & ~0x40C40200; |
---|
| 1727 | |
---|
| 1728 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1729 | whereami("pnic_do_nway\n"); |
---|
| 1730 | #endif |
---|
| 1731 | |
---|
| 1732 | if (phy_reg & 0x78000000) { /* Ignore baseT4 */ |
---|
| 1733 | if (phy_reg & 0x20000000) tp->if_port = 5; |
---|
| 1734 | else if (phy_reg & 0x40000000) tp->if_port = 3; |
---|
| 1735 | else if (phy_reg & 0x10000000) tp->if_port = 4; |
---|
| 1736 | else if (phy_reg & 0x08000000) tp->if_port = 0; |
---|
| 1737 | tp->nwayset = 1; |
---|
| 1738 | new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000; |
---|
| 1739 | outl(0x32 | (tp->if_port & 1), ioaddr + CSR12); |
---|
| 1740 | if (tp->if_port & 1) |
---|
| 1741 | outl(0x1F868, ioaddr + 0xB8); |
---|
| 1742 | if (phy_reg & 0x30000000) { |
---|
| 1743 | tp->full_duplex = 1; |
---|
| 1744 | new_csr6 |= 0x00000200; |
---|
| 1745 | } |
---|
| 1746 | #ifdef TULIP_DEBUG |
---|
| 1747 | if (tulip_debug > 1) |
---|
| 1748 | printf("%s: PNIC autonegotiated status %X, %s.\n", |
---|
| 1749 | tp->nic_name, phy_reg, medianame[tp->if_port]); |
---|
| 1750 | #endif |
---|
| 1751 | if (tp->csr6 != new_csr6) { |
---|
| 1752 | tp->csr6 = new_csr6; |
---|
| 1753 | outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */ |
---|
| 1754 | outl(tp->csr6 | 0x2002, ioaddr + CSR6); |
---|
| 1755 | } |
---|
| 1756 | } |
---|
| 1757 | } |
---|
| 1758 | |
---|
| 1759 | /* Set up the transceiver control registers for the selected media type. */ |
---|
| 1760 | static void select_media(struct nic *nic, int startup) |
---|
| 1761 | { |
---|
| 1762 | struct mediatable *mtable = tp->mtable; |
---|
| 1763 | u32 new_csr6; |
---|
| 1764 | int i; |
---|
| 1765 | |
---|
| 1766 | #ifdef TULIP_DEBUG_WHERE |
---|
| 1767 | whereami("select_media\n"); |
---|
| 1768 | #endif |
---|
| 1769 | |
---|
| 1770 | if (mtable) { |
---|
| 1771 | struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index]; |
---|
| 1772 | unsigned char *p = mleaf->leafdata; |
---|
| 1773 | switch (mleaf->type) { |
---|
| 1774 | case 0: /* 21140 non-MII xcvr. */ |
---|
| 1775 | #ifdef TULIP_DEBUG |
---|
| 1776 | if (tulip_debug > 1) |
---|
| 1777 | printf("%s: Using a 21140 non-MII transceiver" |
---|
| 1778 | " with control setting %hhX.\n", |
---|
| 1779 | tp->nic_name, p[1]); |
---|
| 1780 | #endif |
---|
| 1781 | tp->if_port = p[0]; |
---|
| 1782 | if (startup) |
---|
| 1783 | outl(mtable->csr12dir | 0x100, ioaddr + CSR12); |
---|
| 1784 | outl(p[1], ioaddr + CSR12); |
---|
| 1785 | new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); |
---|
| 1786 | break; |
---|
| 1787 | case 2: case 4: { |
---|
| 1788 | u16 setup[5]; |
---|
| 1789 | u32 csr13val, csr14val, csr15dir, csr15val; |
---|
| 1790 | for (i = 0; i < 5; i++) |
---|
| 1791 | setup[i] = get_u16(&p[i*2 + 1]); |
---|
| 1792 | |
---|
| 1793 | tp->if_port = p[0] & 15; |
---|
| 1794 | if (media_cap[tp->if_port] & MediaAlwaysFD) |
---|
| 1795 | tp->full_duplex = 1; |
---|
| 1796 | |
---|
| 1797 | if (startup && mtable->has_reset) { |
---|
| 1798 | struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; |
---|
| 1799 | unsigned char *rst = rleaf->leafdata; |
---|
| 1800 | #ifdef TULIP_DEBUG |
---|
| 1801 | if (tulip_debug > 1) |
---|
| 1802 | printf("%s: Resetting the transceiver.\n", |
---|
| 1803 | tp->nic_name); |
---|
| 1804 | #endif |
---|
| 1805 | for (i = 0; i < rst[0]; i++) |
---|
| 1806 | outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); |
---|
| 1807 | } |
---|
| 1808 | #ifdef TULIP_DEBUG |
---|
| 1809 | if (tulip_debug > 1) |
---|
| 1810 | printf("%s: 21143 non-MII %s transceiver control " |
---|
| 1811 | "%hX/%hX.\n", |
---|
| 1812 | tp->nic_name, medianame[tp->if_port], setup[0], setup[1]); |
---|
| 1813 | #endif |
---|
| 1814 | if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ |
---|
| 1815 | csr13val = setup[0]; |
---|
| 1816 | csr14val = setup[1]; |
---|
| 1817 | csr15dir = (setup[3]<<16) | setup[2]; |
---|
| 1818 | csr15val = (setup[4]<<16) | setup[2]; |
---|
| 1819 | outl(0, ioaddr + CSR13); |
---|
| 1820 | outl(csr14val, ioaddr + CSR14); |
---|
| 1821 | outl(csr15dir, ioaddr + CSR15); /* Direction */ |
---|
| 1822 | outl(csr15val, ioaddr + CSR15); /* Data */ |
---|
| 1823 | outl(csr13val, ioaddr + CSR13); |
---|
| 1824 | } else { |
---|
| 1825 | csr13val = 1; |
---|
| 1826 | csr14val = 0x0003FF7F; |
---|
| 1827 | csr15dir = (setup[0]<<16) | 0x0008; |
---|
| 1828 | csr15val = (setup[1]<<16) | 0x0008; |
---|
| 1829 | if (tp->if_port <= 4) |
---|
| 1830 | csr14val = t21142_csr14[tp->if_port]; |
---|
| 1831 | if (startup) { |
---|
| 1832 | outl(0, ioaddr + CSR13); |
---|
| 1833 | outl(csr14val, ioaddr + CSR14); |
---|
| 1834 | } |
---|
| 1835 | outl(csr15dir, ioaddr + CSR15); /* Direction */ |
---|
| 1836 | outl(csr15val, ioaddr + CSR15); /* Data */ |
---|
| 1837 | if (startup) outl(csr13val, ioaddr + CSR13); |
---|
| 1838 | } |
---|
| 1839 | #ifdef TULIP_DEBUG |
---|
| 1840 | if (tulip_debug > 1) |
---|
| 1841 | printf("%s: Setting CSR15 to %X/%X.\n", |
---|
| 1842 | tp->nic_name, csr15dir, csr15val); |
---|
| 1843 | #endif |
---|
| 1844 | if (mleaf->type == 4) |
---|
| 1845 | new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); |
---|
| 1846 | else |
---|
| 1847 | new_csr6 = 0x82420000; |
---|
| 1848 | break; |
---|
| 1849 | } |
---|
| 1850 | case 1: case 3: { |
---|
| 1851 | int phy_num = p[0]; |
---|
| 1852 | int init_length = p[1]; |
---|
| 1853 | u16 *misc_info; |
---|
| 1854 | |
---|
| 1855 | tp->if_port = 11; |
---|
| 1856 | new_csr6 = 0x020E0000; |
---|
| 1857 | if (mleaf->type == 3) { /* 21142 */ |
---|
| 1858 | u16 *init_sequence = (u16*)(p+2); |
---|
| 1859 | u16 *reset_sequence = &((u16*)(p+3))[init_length]; |
---|
| 1860 | int reset_length = p[2 + init_length*2]; |
---|
| 1861 | misc_info = reset_sequence + reset_length; |
---|
| 1862 | if (startup) |
---|
| 1863 | for (i = 0; i < reset_length; i++) |
---|
| 1864 | outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); |
---|
| 1865 | for (i = 0; i < init_length; i++) |
---|
| 1866 | outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); |
---|
| 1867 | } else { |
---|
| 1868 | u8 *init_sequence = p + 2; |
---|
| 1869 | u8 *reset_sequence = p + 3 + init_length; |
---|
| 1870 | int reset_length = p[2 + init_length]; |
---|
| 1871 | misc_info = (u16*)(reset_sequence + reset_length); |
---|
| 1872 | if (startup) { |
---|
| 1873 | outl(mtable->csr12dir | 0x100, ioaddr + CSR12); |
---|
| 1874 | for (i = 0; i < reset_length; i++) |
---|
| 1875 | outl(reset_sequence[i], ioaddr + CSR12); |
---|
| 1876 | } |
---|
| 1877 | for (i = 0; i < init_length; i++) |
---|
| 1878 | outl(init_sequence[i], ioaddr + CSR12); |
---|
| 1879 | } |
---|
| 1880 | tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1; |
---|
| 1881 | if (startup < 2) { |
---|
| 1882 | if (tp->mii_advertise == 0) |
---|
| 1883 | tp->mii_advertise = tp->advertising[phy_num]; |
---|
| 1884 | #ifdef TULIP_DEBUG |
---|
| 1885 | if (tulip_debug > 1) |
---|
| 1886 | printf("%s: Advertising %hX on MII %d.\n", |
---|
| 1887 | tp->nic_name, tp->mii_advertise, tp->phys[phy_num]); |
---|
| 1888 | #endif |
---|
| 1889 | mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise); |
---|
| 1890 | } |
---|
| 1891 | break; |
---|
| 1892 | } |
---|
| 1893 | default: |
---|
| 1894 | printf("%s: Invalid media table selection %d.\n", |
---|
| 1895 | tp->nic_name, mleaf->type); |
---|
| 1896 | new_csr6 = 0x020E0000; |
---|
| 1897 | } |
---|
| 1898 | #ifdef TULIP_DEBUG |
---|
| 1899 | if (tulip_debug > 1) |
---|
| 1900 | printf("%s: Using media type %s, CSR12 is %hhX.\n", |
---|
| 1901 | tp->nic_name, medianame[tp->if_port], |
---|
| 1902 | inl(ioaddr + CSR12) & 0xff); |
---|
| 1903 | #endif |
---|
| 1904 | } else if (tp->chip_id == DC21041) { |
---|
| 1905 | int port = tp->if_port <= 4 ? tp->if_port : 0; |
---|
| 1906 | #ifdef TULIP_DEBUG |
---|
| 1907 | if (tulip_debug > 1) |
---|
| 1908 | printf("%s: 21041 using media %s, CSR12 is %hX.\n", |
---|
| 1909 | tp->nic_name, medianame[port == 3 ? 12: port], |
---|
| 1910 | inl(ioaddr + CSR12)); |
---|
| 1911 | #endif |
---|
| 1912 | outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ |
---|
| 1913 | outl(t21041_csr14[port], ioaddr + CSR14); |
---|
| 1914 | outl(t21041_csr15[port], ioaddr + CSR15); |
---|
| 1915 | outl(t21041_csr13[port], ioaddr + CSR13); |
---|
| 1916 | new_csr6 = 0x80020000; |
---|
| 1917 | } else if (tp->chip_id == LC82C168) { |
---|
| 1918 | if (startup && ! tp->medialock) |
---|
| 1919 | tp->if_port = tp->mii_cnt ? 11 : 0; |
---|
| 1920 | #ifdef TULIP_DEBUG |
---|
| 1921 | if (tulip_debug > 1) |
---|
| 1922 | printf("%s: PNIC PHY status is %hX, media %s.\n", |
---|
| 1923 | tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]); |
---|
| 1924 | #endif |
---|
| 1925 | if (tp->mii_cnt) { |
---|
| 1926 | new_csr6 = 0x810C0000; |
---|
| 1927 | outl(0x0001, ioaddr + CSR15); |
---|
| 1928 | outl(0x0201B07A, ioaddr + 0xB8); |
---|
| 1929 | } else if (startup) { |
---|
| 1930 | /* Start with 10mbps to do autonegotiation. */ |
---|
| 1931 | outl(0x32, ioaddr + CSR12); |
---|
| 1932 | new_csr6 = 0x00420000; |
---|
| 1933 | outl(0x0001B078, ioaddr + 0xB8); |
---|
| 1934 | outl(0x0201B078, ioaddr + 0xB8); |
---|
| 1935 | } else if (tp->if_port == 3 || tp->if_port == 5) { |
---|
| 1936 | outl(0x33, ioaddr + CSR12); |
---|
| 1937 | new_csr6 = 0x01860000; |
---|
| 1938 | /* Trigger autonegotiation. */ |
---|
| 1939 | outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8); |
---|
| 1940 | } else { |
---|
| 1941 | outl(0x32, ioaddr + CSR12); |
---|
| 1942 | new_csr6 = 0x00420000; |
---|
| 1943 | outl(0x1F078, ioaddr + 0xB8); |
---|
| 1944 | } |
---|
| 1945 | } else if (tp->chip_id == DC21040) { /* 21040 */ |
---|
| 1946 | /* Turn on the xcvr interface. */ |
---|
| 1947 | #ifdef TULIP_DEBUG |
---|
| 1948 | int csr12 = inl(ioaddr + CSR12); |
---|
| 1949 | if (tulip_debug > 1) |
---|
| 1950 | printf("%s: 21040 media type is %s, CSR12 is %hhX.\n", |
---|
| 1951 | tp->nic_name, medianame[tp->if_port], csr12); |
---|
| 1952 | #endif |
---|
| 1953 | if (media_cap[tp->if_port] & MediaAlwaysFD) |
---|
| 1954 | tp->full_duplex = 1; |
---|
| 1955 | new_csr6 = 0x20000; |
---|
| 1956 | /* Set the full duplux match frame. */ |
---|
| 1957 | outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11); |
---|
| 1958 | outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ |
---|
| 1959 | if (t21040_csr13[tp->if_port] & 8) { |
---|
| 1960 | outl(0x0705, ioaddr + CSR14); |
---|
| 1961 | outl(0x0006, ioaddr + CSR15); |
---|
| 1962 | } else { |
---|
| 1963 | outl(0xffff, ioaddr + CSR14); |
---|
| 1964 | outl(0x0000, ioaddr + CSR15); |
---|
| 1965 | } |
---|
| 1966 | outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13); |
---|
| 1967 | } else { /* Unknown chip type with no media table. */ |
---|
| 1968 | if (tp->default_port == 0) |
---|
| 1969 | tp->if_port = tp->mii_cnt ? 11 : 3; |
---|
| 1970 | if (media_cap[tp->if_port] & MediaIsMII) { |
---|
| 1971 | new_csr6 = 0x020E0000; |
---|
| 1972 | } else if (media_cap[tp->if_port] & MediaIsFx) { |
---|
| 1973 | new_csr6 = 0x028600000; |
---|
| 1974 | } else |
---|
| 1975 | new_csr6 = 0x038600000; |
---|
| 1976 | #ifdef TULIP_DEBUG |
---|
| 1977 | if (tulip_debug > 1) |
---|
| 1978 | printf("%s: No media description table, assuming " |
---|
| 1979 | "%s transceiver, CSR12 %hhX.\n", |
---|
| 1980 | tp->nic_name, medianame[tp->if_port], |
---|
| 1981 | inl(ioaddr + CSR12)); |
---|
| 1982 | #endif |
---|
| 1983 | } |
---|
| 1984 | |
---|
| 1985 | tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); |
---|
| 1986 | return; |
---|
| 1987 | } |
---|
| 1988 | |
---|
| 1989 | /* |
---|
| 1990 | Check the MII negotiated duplex and change the CSR6 setting if |
---|
| 1991 | required. |
---|
| 1992 | Return 0 if everything is OK. |
---|
| 1993 | Return < 0 if the transceiver is missing or has no link beat. |
---|
| 1994 | */ |
---|
| 1995 | static int tulip_check_duplex(struct nic *nic) |
---|
| 1996 | { |
---|
| 1997 | unsigned int bmsr, lpa, negotiated, new_csr6; |
---|
| 1998 | |
---|
| 1999 | bmsr = mdio_read(nic, tp->phys[0], 1); |
---|
| 2000 | lpa = mdio_read(nic, tp->phys[0], 5); |
---|
| 2001 | |
---|
| 2002 | #ifdef TULIP_DEBUG |
---|
| 2003 | if (tulip_debug > 1) |
---|
| 2004 | printf("%s: MII status %#x, Link partner report " |
---|
| 2005 | "%#x.\n", tp->nic_name, bmsr, lpa); |
---|
| 2006 | #endif |
---|
| 2007 | |
---|
| 2008 | if (bmsr == 0xffff) |
---|
| 2009 | return -2; |
---|
| 2010 | if ((bmsr & 4) == 0) { |
---|
| 2011 | int new_bmsr = mdio_read(nic, tp->phys[0], 1); |
---|
| 2012 | if ((new_bmsr & 4) == 0) { |
---|
| 2013 | #ifdef TULIP_DEBUG |
---|
| 2014 | if (tulip_debug > 1) |
---|
| 2015 | printf("%s: No link beat on the MII interface," |
---|
| 2016 | " status %#x.\n", tp->nic_name, |
---|
| 2017 | new_bmsr); |
---|
| 2018 | #endif |
---|
| 2019 | return -1; |
---|
| 2020 | } |
---|
| 2021 | } |
---|
| 2022 | tp->full_duplex = lpa & 0x140; |
---|
| 2023 | |
---|
| 2024 | new_csr6 = tp->csr6; |
---|
| 2025 | negotiated = lpa & tp->advertising[0]; |
---|
| 2026 | |
---|
| 2027 | if(negotiated & 0x380) new_csr6 &= ~0x400000; |
---|
| 2028 | else new_csr6 |= 0x400000; |
---|
| 2029 | if (tp->full_duplex) new_csr6 |= 0x200; |
---|
| 2030 | else new_csr6 &= ~0x200; |
---|
| 2031 | |
---|
| 2032 | if (new_csr6 != tp->csr6) { |
---|
| 2033 | tp->csr6 = new_csr6; |
---|
| 2034 | |
---|
| 2035 | #ifdef TULIP_DEBUG |
---|
| 2036 | if (tulip_debug > 0) |
---|
| 2037 | printf("%s: Setting %s-duplex based on MII" |
---|
| 2038 | "#%d link partner capability of %#x.\n", |
---|
| 2039 | tp->nic_name, |
---|
| 2040 | tp->full_duplex ? "full" : "half", |
---|
| 2041 | tp->phys[0], lpa); |
---|
| 2042 | #endif |
---|
| 2043 | return 1; |
---|
| 2044 | } |
---|
| 2045 | |
---|
| 2046 | return 0; |
---|
| 2047 | } |
---|
| 2048 | |
---|
| 2049 | static struct pci_device_id tulip_nics[] = { |
---|
| 2050 | PCI_ROM(0x1011, 0x0002, "dc21040", "Digital Tulip", 0), |
---|
| 2051 | PCI_ROM(0x1011, 0x0009, "ds21140", "Digital Tulip Fast", 0), |
---|
| 2052 | PCI_ROM(0x1011, 0x0014, "dc21041", "Digital Tulip+", 0), |
---|
| 2053 | PCI_ROM(0x1011, 0x0019, "ds21142", "Digital Tulip 21142", 0), |
---|
| 2054 | PCI_ROM(0x10b7, 0x9300, "3csoho100b-tx","3ComSOHO100B-TX", 0), |
---|
| 2055 | PCI_ROM(0x10b9, 0x5261, "ali1563", "ALi 1563 integrated ethernet", 0), |
---|
| 2056 | PCI_ROM(0x10d9, 0x0512, "mx98713", "Macronix MX987x3", 0), |
---|
| 2057 | PCI_ROM(0x10d9, 0x0531, "mx98715", "Macronix MX987x5", 0), |
---|
| 2058 | PCI_ROM(0x1113, 0x1217, "mxic-98715", "Macronix MX987x5", 0), |
---|
| 2059 | PCI_ROM(0x11ad, 0xc115, "lc82c115", "LinkSys LNE100TX", 0), |
---|
| 2060 | PCI_ROM(0x11ad, 0x0002, "82c168", "Netgear FA310TX", 0), |
---|
| 2061 | PCI_ROM(0x1282, 0x9100, "dm9100", "Davicom 9100", 0), |
---|
| 2062 | PCI_ROM(0x1282, 0x9102, "dm9102", "Davicom 9102", 0), |
---|
| 2063 | PCI_ROM(0x1282, 0x9009, "dm9009", "Davicom 9009", 0), |
---|
| 2064 | PCI_ROM(0x1282, 0x9132, "dm9132", "Davicom 9132", 0), |
---|
| 2065 | PCI_ROM(0x1317, 0x0985, "centaur-p", "ADMtek Centaur-P", 0), |
---|
| 2066 | PCI_ROM(0x1317, 0x0981, "an981", "ADMtek AN981 Comet", 0), /* ADMTek Centaur-P (stmicro) */ |
---|
| 2067 | PCI_ROM(0x1113, 0x1216, "an983", "ADMTek AN983 Comet", 0), |
---|
| 2068 | PCI_ROM(0x1317, 0x9511, "an983b", "ADMTek Comet 983b", 0), |
---|
| 2069 | PCI_ROM(0x1317, 0x1985, "centaur-c", "ADMTek Centaur-C", 0), |
---|
| 2070 | PCI_ROM(0x8086, 0x0039, "intel21145", "Intel Tulip", 0), |
---|
| 2071 | PCI_ROM(0x125b, 0x1400, "ax88140", "ASIX AX88140", 0), |
---|
| 2072 | PCI_ROM(0x11f6, 0x9881, "rl100tx", "Compex RL100-TX", 0), |
---|
| 2073 | PCI_ROM(0x115d, 0x0003, "xircomtulip", "Xircom Tulip", 0), |
---|
| 2074 | PCI_ROM(0x104a, 0x0981, "tulip-0981", "Tulip 0x104a 0x0981", 0), |
---|
| 2075 | PCI_ROM(0x104a, 0x2774, "SGThomson-STE10100A", "Tulip 0x104a 0x2774", 0), /*Modified by Ramesh Chander*/ |
---|
| 2076 | PCI_ROM(0x1113, 0x9511, "tulip-9511", "Tulip 0x1113 0x9511", 0), |
---|
| 2077 | PCI_ROM(0x1186, 0x1561, "tulip-1561", "Tulip 0x1186 0x1561", 0), |
---|
| 2078 | PCI_ROM(0x1259, 0xa120, "tulip-a120", "Tulip 0x1259 0xa120", 0), |
---|
| 2079 | PCI_ROM(0x13d1, 0xab02, "tulip-ab02", "Tulip 0x13d1 0xab02", 0), |
---|
| 2080 | PCI_ROM(0x13d1, 0xab03, "tulip-ab03", "Tulip 0x13d1 0xab03", 0), |
---|
| 2081 | PCI_ROM(0x13d1, 0xab08, "tulip-ab08", "Tulip 0x13d1 0xab08", 0), |
---|
| 2082 | PCI_ROM(0x14f1, 0x1803, "lanfinity", "Conexant LANfinity", 0), |
---|
| 2083 | PCI_ROM(0x1626, 0x8410, "tulip-8410", "Tulip 0x1626 0x8410", 0), |
---|
| 2084 | PCI_ROM(0x1737, 0xab08, "tulip-1737-ab08","Tulip 0x1737 0xab08", 0), |
---|
| 2085 | PCI_ROM(0x1737, 0xab09, "tulip-ab09", "Tulip 0x1737 0xab09", 0), |
---|
| 2086 | }; |
---|
| 2087 | |
---|
| 2088 | PCI_DRIVER ( tulip_driver, tulip_nics, PCI_NO_CLASS ); |
---|
| 2089 | |
---|
| 2090 | DRIVER ( "Tulip", nic_driver, pci_driver, tulip_driver, |
---|
| 2091 | tulip_probe, tulip_disable ); |
---|
| 2092 | |
---|
| 2093 | /* |
---|
| 2094 | * Local variables: |
---|
| 2095 | * c-basic-offset: 8 |
---|
| 2096 | * c-indent-level: 8 |
---|
| 2097 | * tab-width: 8 |
---|
| 2098 | * End: |
---|
| 2099 | */ |
---|