00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 FILE_LICENCE ( GPL_ANY );
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #include "etherboot.h"
00112 #include "nic.h"
00113
00114 #include <gpxe/ethernet.h>
00115 #include <gpxe/pci.h>
00116
00117
00118
00119 #undef TULIP_DEBUG
00120 #undef TULIP_DEBUG_WHERE
00121 #ifdef TULIP_DEBUG
00122 static int tulip_debug = 2;
00123 #endif
00124
00125 #define TX_TIME_OUT 2*TICKS_PER_SEC
00126
00127
00128
00129 #define get_unaligned(ptr) (*(ptr))
00130 #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
00131 #define get_u16(ptr) (*(u16 *)(ptr))
00132 #define virt_to_le32desc(addr) virt_to_bus(addr)
00133
00134 #define TULIP_IOTYPE PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
00135 #define TULIP_SIZE 0x80
00136
00137
00138
00139
00140
00141 #define FULL_DUPLEX_MAGIC 0x6969
00142
00143 static const int csr0 = 0x01A00000 | 0x8000;
00144
00145
00146 #define MEDIA_MASK 31
00147 static const char * const medianame[32] = {
00148 "10baseT", "10base2", "AUI", "100baseTx",
00149 "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
00150 "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
00151 "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
00152 "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
00153 };
00154
00155
00156 enum tulip_chips {
00157 DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
00158 LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
00159 COMPEX9881, I21145, XIRCOM, SGThomson,
00160 };
00161
00162 enum pci_id_flags_bits {
00163
00164 PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
00165
00166 PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
00167 PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
00168 PCI_UNUSED_IRQ=0x800,
00169 };
00170
00171 struct pci_id_info {
00172 char *name;
00173 struct match_info {
00174 u32 pci, pci_mask, subsystem, subsystem_mask;
00175 u32 revision, revision_mask;
00176 } id;
00177 enum pci_id_flags_bits pci_flags;
00178 int io_size;
00179 int drv_flags;
00180 };
00181
00182 static const struct pci_id_info pci_id_tbl[] = {
00183 { "Digital DC21040 Tulip", { 0x00021011, 0xffffffff, 0, 0, 0, 0 },
00184 TULIP_IOTYPE, 0x80, DC21040 },
00185 { "Digital DC21041 Tulip", { 0x00141011, 0xffffffff, 0, 0, 0, 0 },
00186 TULIP_IOTYPE, 0x80, DC21041 },
00187 { "Digital DS21140A Tulip", { 0x00091011, 0xffffffff, 0,0, 0x20,0xf0 },
00188 TULIP_IOTYPE, 0x80, DC21140 },
00189 { "Digital DS21140 Tulip", { 0x00091011, 0xffffffff, 0, 0, 0, 0 },
00190 TULIP_IOTYPE, 0x80, DC21140 },
00191 { "Digital DS21143 Tulip", { 0x00191011, 0xffffffff, 0,0, 65,0xff },
00192 TULIP_IOTYPE, TULIP_SIZE, DC21142 },
00193 { "Digital DS21142 Tulip", { 0x00191011, 0xffffffff, 0, 0, 0, 0 },
00194 TULIP_IOTYPE, TULIP_SIZE, DC21142 },
00195 { "Kingston KNE110tx (PNIC)", { 0x000211AD, 0xffffffff, 0xf0022646, 0xffffffff, 0, 0 },
00196 TULIP_IOTYPE, 256, LC82C168 },
00197 { "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff, 0, 0, 0, 0 },
00198 TULIP_IOTYPE, 256, LC82C168 },
00199 { "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff, 0, 0, 0, 0 },
00200 TULIP_IOTYPE, 256, MX98713 },
00201 { "Macronix 98715 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
00202 TULIP_IOTYPE, 256, MX98715 },
00203 { "Macronix 98725 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
00204 TULIP_IOTYPE, 256, MX98725 },
00205 { "ASIX AX88141", { 0x1400125B, 0xffffffff, 0,0, 0x10, 0xf0 },
00206 TULIP_IOTYPE, 128, AX88141 },
00207 { "ASIX AX88140", { 0x1400125B, 0xffffffff, 0, 0, 0, 0 },
00208 TULIP_IOTYPE, 128, AX88140 },
00209 { "Lite-On LC82C115 PNIC-II", { 0xc11511AD, 0xffffffff, 0, 0, 0, 0 },
00210 TULIP_IOTYPE, 256, PNIC2 },
00211 { "ADMtek AN981 Comet", { 0x09811317, 0xffffffff, 0, 0, 0, 0 },
00212 TULIP_IOTYPE, 256, COMET },
00213 { "ADMTek AN983 Comet", { 0x12161113, 0xffffffff, 0, 0, 0, 0 },
00214 TULIP_IOTYPE, 256, COMET },
00215 { "ADMTek Comet AN983b", { 0x95111317, 0xffffffff, 0, 0, 0, 0 },
00216 TULIP_IOTYPE, 256, COMET },
00217 { "ADMtek Centaur-P", { 0x09851317, 0xffffffff, 0, 0, 0, 0 },
00218 TULIP_IOTYPE, 256, COMET },
00219 { "ADMtek Centaur-C", { 0x19851317, 0xffffffff, 0, 0, 0, 0 },
00220 TULIP_IOTYPE, 256, COMET },
00221 { "Compex RL100-TX", { 0x988111F6, 0xffffffff, 0, 0, 0, 0 },
00222 TULIP_IOTYPE, 128, COMPEX9881 },
00223 { "Intel 21145 Tulip", { 0x00398086, 0xffffffff, 0, 0, 0, 0 },
00224 TULIP_IOTYPE, 128, I21145 },
00225 { "Xircom Tulip clone", { 0x0003115d, 0xffffffff, 0, 0, 0, 0 },
00226 TULIP_IOTYPE, 128, XIRCOM },
00227 { "Davicom DM9102", { 0x91021282, 0xffffffff, 0, 0, 0, 0 },
00228 TULIP_IOTYPE, 0x80, DC21140 },
00229 { "Davicom DM9100", { 0x91001282, 0xffffffff, 0, 0, 0, 0 },
00230 TULIP_IOTYPE, 0x80, DC21140 },
00231 { "Macronix mxic-98715 (EN1217)", { 0x12171113, 0xffffffff, 0, 0, 0, 0 },
00232 TULIP_IOTYPE, 256, MX98715 },
00233 { "3Com 3cSOHO100B-TX (ADMtek Centuar)", { 0x930010b7, 0xffffffff, 0, 0, 0, 0 },
00234 TULIP_IOTYPE, TULIP_SIZE, COMET },
00235 { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 },
00236 TULIP_IOTYPE, 256, COMET },
00237 { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 },
00238 };
00239
00240 enum tbl_flag {
00241 HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
00242 HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20,
00243 HAS_PNICNWAY=0x80, HAS_NWAY=0x40,
00244 HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400,
00245 };
00246
00247
00248 static struct tulip_chip_table {
00249 char *chip_name;
00250 int flags;
00251 } tulip_tbl[] = {
00252 { "Digital DC21040 Tulip", 0},
00253 { "Digital DC21041 Tulip", HAS_MEDIA_TABLE | HAS_NWAY },
00254 { "Digital DS21140 Tulip", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
00255 { "Digital DS21143 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
00256 | HAS_PWRDWN | HAS_NWAY | HAS_INTR_MITIGATION },
00257 { "Lite-On 82c168 PNIC", HAS_MII | HAS_PNICNWAY },
00258 { "Macronix 98713 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
00259 { "Macronix 98715 PMAC", HAS_MEDIA_TABLE },
00260 { "Macronix 98725 PMAC", HAS_MEDIA_TABLE },
00261 { "ASIX AX88140", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM
00262 | MC_HASH_ONLY | IS_ASIX },
00263 { "ASIX AX88141", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
00264 | IS_ASIX },
00265 { "Lite-On PNIC-II", HAS_MII | HAS_NWAY | HAS_8023X },
00266 { "ADMtek Comet", HAS_MII | MC_HASH_ONLY },
00267 { "Compex 9881 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
00268 { "Intel DS21145 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
00269 | HAS_PWRDWN | HAS_NWAY },
00270 { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
00271 | HAS_PWRDWN | HAS_NWAY },
00272 { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY },
00273 { 0, 0 },
00274 };
00275
00276
00277 enum MediaIs {
00278 MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
00279 MediaIs100=16};
00280
00281 static const char media_cap[32] =
00282 {0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 20,31,0,0, };
00283 static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0};
00284
00285
00286 static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
00287 static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
00288 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
00289
00290
00291
00292
00293 static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
00294
00295
00296
00297
00298
00299
00300 enum tulip_offsets {
00301 CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
00302 CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
00303 CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
00304 };
00305
00306
00307 enum status_bits {
00308 TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
00309 NormalIntr=0x10000, AbnormalIntr=0x8000,
00310 RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
00311 TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
00312 };
00313
00314
00315 enum csr6_mode_bits {
00316 TxOn=0x2000, RxOn=0x0002, FullDuplex=0x0200,
00317 AcceptBroadcast=0x0100, AcceptAllMulticast=0x0080,
00318 AcceptAllPhys=0x0040, AcceptRunt=0x0008,
00319 };
00320
00321
00322 enum desc_status_bits {
00323 DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
00324 };
00325
00326 struct medialeaf {
00327 u8 type;
00328 u8 media;
00329 unsigned char *leafdata;
00330 };
00331
00332 struct mediatable {
00333 u16 defaultmedia;
00334 u8 leafcount, csr12dir;
00335 unsigned has_mii:1, has_nonmii:1, has_reset:6;
00336 u32 csr15dir, csr15val;
00337 struct medialeaf mleaf[0];
00338 };
00339
00340 struct mediainfo {
00341 struct mediainfo *next;
00342 int info_type;
00343 int index;
00344 unsigned char *info;
00345 };
00346
00347
00348 #define EEPROM_ADDRLEN 6
00349 #define EEPROM_SIZE 128
00350
00351
00352 #define EE_WRITE_CMD (5 << addr_len)
00353 #define EE_READ_CMD (6 << addr_len)
00354 #define EE_ERASE_CMD (7 << addr_len)
00355
00356
00357 #define EE_SHIFT_CLK 0x02
00358 #define EE_CS 0x01
00359 #define EE_DATA_WRITE 0x04
00360 #define EE_WRITE_0 0x01
00361 #define EE_WRITE_1 0x05
00362 #define EE_DATA_READ 0x08
00363 #define EE_ENB (0x4800 | EE_CS)
00364
00365
00366
00367
00368 #define eeprom_delay() inl(ee_addr)
00369
00370
00371 #define BUFLEN 1536
00372
00373
00374
00375
00376
00377
00378
00379
00380 #define DESC_RING_WRAP 0x02000000
00381
00382
00383 struct tulip_rx_desc {
00384 volatile u32 status;
00385 u32 length;
00386 u32 buffer1, buffer2;
00387 };
00388
00389 struct tulip_tx_desc {
00390 volatile u32 status;
00391 u32 length;
00392 u32 buffer1, buffer2;
00393 };
00394
00395
00396
00397
00398
00399 static u32 ioaddr;
00400
00401 struct tulip_private {
00402 int cur_rx;
00403 int chip_id;
00404 int pci_id_idx;
00405 int revision;
00406 int flags;
00407 unsigned short vendor_id;
00408 unsigned short dev_id;
00409 unsigned char ehdr[ETH_HLEN];
00410 const char *nic_name;
00411 unsigned int csr0, csr6;
00412 unsigned int if_port;
00413 unsigned int full_duplex;
00414 unsigned int full_duplex_lock;
00415 unsigned int medialock;
00416 unsigned int mediasense;
00417 unsigned int nway, nwayset;
00418 unsigned int default_port;
00419 unsigned char eeprom[EEPROM_SIZE];
00420 u8 media_table_storage[(sizeof(struct mediatable) + 32*sizeof(struct medialeaf))];
00421 u16 sym_advertise, mii_advertise;
00422 struct mediatable *mtable;
00423 u16 lpar;
00424 u16 advertising[4];
00425 signed char phys[4], mii_cnt;
00426 int cur_index;
00427 int saved_if_port;
00428 };
00429
00430
00431
00432
00433 #define TX_RING_SIZE 2
00434 #define RX_RING_SIZE 4
00435 struct {
00436 struct tulip_tx_desc tx_ring[TX_RING_SIZE];
00437 unsigned char txb[BUFLEN];
00438 struct tulip_rx_desc rx_ring[RX_RING_SIZE];
00439 unsigned char rxb[RX_RING_SIZE * BUFLEN];
00440 struct tulip_private tpx;
00441 } tulip_bss __shared __attribute__ ((aligned(4)));
00442 #define tx_ring tulip_bss.tx_ring
00443 #define txb tulip_bss.txb
00444 #define rx_ring tulip_bss.rx_ring
00445 #define rxb tulip_bss.rxb
00446
00447 static struct tulip_private *tp;
00448
00449
00450
00451
00452 static struct fixups {
00453 char *name;
00454 unsigned char addr0, addr1, addr2;
00455 u16 newtable[32];
00456 } eeprom_fixups[] = {
00457 {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
00458 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
00459 {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
00460 0x0000, 0x009E,
00461 0x0004, 0x009E,
00462 0x0903, 0x006D,
00463 0x0905, 0x006D, }},
00464 {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
00465 0x0107, 0x8021,
00466 0x0108, 0x8021,
00467 0x0100, 0x009E,
00468 0x0104, 0x009E,
00469 0x0103, 0x006D,
00470 0x0105, 0x006D, }},
00471 {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
00472 0x1001, 0x009E,
00473 0x0000, 0x009E,
00474 0x0004, 0x009E,
00475 0x0303, 0x006D,
00476 0x0305, 0x006D, }},
00477 {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
00478 0x1B01, 0x0000,
00479 0x0B00, 0x009E,
00480 0x0B04, 0x009E,
00481 0x1B03, 0x006D,
00482 0x1B05, 0x006D,
00483 }},
00484 {0, 0, 0, 0, {}}};
00485
00486 static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
00487 "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
00488
00489
00490
00491
00492
00493 static int mdio_read(struct nic *nic, int phy_id, int location);
00494 static void mdio_write(struct nic *nic, int phy_id, int location, int value);
00495 static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
00496 static void parse_eeprom(struct nic *nic);
00497 static int tulip_probe(struct nic *nic,struct pci_device *pci);
00498 static void tulip_init_ring(struct nic *nic);
00499 static void tulip_reset(struct nic *nic);
00500 static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
00501 unsigned int s, const char *p);
00502 static int tulip_poll(struct nic *nic, int retrieve);
00503 static void tulip_disable(struct nic *nic);
00504 static void nway_start(struct nic *nic);
00505 static void pnic_do_nway(struct nic *nic);
00506 static void select_media(struct nic *nic, int startup);
00507 static void init_media(struct nic *nic);
00508 static void start_link(struct nic *nic);
00509 static int tulip_check_duplex(struct nic *nic);
00510
00511 static void tulip_wait(unsigned int nticks);
00512
00513 #ifdef TULIP_DEBUG_WHERE
00514 static void whereami(const char *str);
00515 #endif
00516
00517 #ifdef TULIP_DEBUG
00518 static void tulip_more(void);
00519 #endif
00520
00521
00522
00523
00524
00525
00526 #ifdef TULIP_DEBUG_WHERE
00527 static void whereami (const char *str, struct pci_device *pci)
00528 {
00529 printf("%s: %s\n", tp->nic_name, str);
00530
00531 }
00532 #endif
00533
00534 #ifdef TULIP_DEBUG
00535 static void tulip_more(void)
00536 {
00537 printf("\n\n-- more --");
00538 while (!iskey())
00539 ;
00540 getchar();
00541 printf("\n\n");
00542 }
00543 #endif
00544
00545 static void tulip_wait(unsigned int nticks)
00546 {
00547 unsigned int to = currticks() + nticks;
00548 while (currticks() < to)
00549 ;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 #define mdio_delay() inl(mdio_addr)
00566
00567
00568
00569
00570 #define MDIO_SHIFT_CLK 0x10000
00571 #define MDIO_DATA_WRITE0 0x00000
00572 #define MDIO_DATA_WRITE1 0x20000
00573 #define MDIO_ENB 0x00000
00574 #define MDIO_ENB_IN 0x40000
00575 #define MDIO_DATA_READ 0x80000
00576
00577
00578
00579
00580
00581
00582 int mdio_read(struct nic *nic __unused, int phy_id, int location)
00583 {
00584 int i;
00585 int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
00586 int retval = 0;
00587 long mdio_addr = ioaddr + CSR9;
00588
00589 #ifdef TULIP_DEBUG_WHERE
00590 whereami("mdio_read\n");
00591 #endif
00592
00593 if (tp->chip_id == LC82C168) {
00594 int i = 1000;
00595 outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
00596 inl(ioaddr + 0xA0);
00597 inl(ioaddr + 0xA0);
00598 while (--i > 0)
00599 if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
00600 return retval & 0xffff;
00601 return 0xffff;
00602 }
00603
00604 if (tp->chip_id == COMET) {
00605 if (phy_id == 1) {
00606 if (location < 7)
00607 return inl(ioaddr + 0xB4 + (location<<2));
00608 else if (location == 17)
00609 return inl(ioaddr + 0xD0);
00610 else if (location >= 29 && location <= 31)
00611 return inl(ioaddr + 0xD4 + ((location-29)<<2));
00612 }
00613 return 0xffff;
00614 }
00615
00616
00617 for (i = 32; i >= 0; i--) {
00618 outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
00619 mdio_delay();
00620 outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
00621 mdio_delay();
00622 }
00623
00624 for (i = 15; i >= 0; i--) {
00625 int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
00626
00627 outl(MDIO_ENB | dataval, mdio_addr);
00628 mdio_delay();
00629 outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
00630 mdio_delay();
00631 }
00632
00633 for (i = 19; i > 0; i--) {
00634 outl(MDIO_ENB_IN, mdio_addr);
00635 mdio_delay();
00636 retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
00637 outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
00638 mdio_delay();
00639 }
00640 return (retval>>1) & 0xffff;
00641 }
00642
00643 void mdio_write(struct nic *nic __unused, int phy_id, int location, int value)
00644 {
00645 int i;
00646 int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
00647 long mdio_addr = ioaddr + CSR9;
00648
00649 #ifdef TULIP_DEBUG_WHERE
00650 whereami("mdio_write\n");
00651 #endif
00652
00653 if (tp->chip_id == LC82C168) {
00654 int i = 1000;
00655 outl(cmd, ioaddr + 0xA0);
00656 do
00657 if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
00658 break;
00659 while (--i > 0);
00660 return;
00661 }
00662
00663 if (tp->chip_id == COMET) {
00664 if (phy_id != 1)
00665 return;
00666 if (location < 7)
00667 outl(value, ioaddr + 0xB4 + (location<<2));
00668 else if (location == 17)
00669 outl(value, ioaddr + 0xD0);
00670 else if (location >= 29 && location <= 31)
00671 outl(value, ioaddr + 0xD4 + ((location-29)<<2));
00672 return;
00673 }
00674
00675
00676 for (i = 32; i >= 0; i--) {
00677 outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
00678 mdio_delay();
00679 outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
00680 mdio_delay();
00681 }
00682
00683 for (i = 31; i >= 0; i--) {
00684 int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
00685 outl(MDIO_ENB | dataval, mdio_addr);
00686 mdio_delay();
00687 outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
00688 mdio_delay();
00689 }
00690
00691 for (i = 2; i > 0; i--) {
00692 outl(MDIO_ENB_IN, mdio_addr);
00693 mdio_delay();
00694 outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
00695 mdio_delay();
00696 }
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
00708 {
00709 int i;
00710 unsigned short retval = 0;
00711 long ee_addr = ioaddr + CSR9;
00712 int read_cmd = location | EE_READ_CMD;
00713
00714 #ifdef TULIP_DEBUG_WHERE
00715 whereami("read_eeprom\n");
00716 #endif
00717
00718 outl(EE_ENB & ~EE_CS, ee_addr);
00719 outl(EE_ENB, ee_addr);
00720
00721
00722 for (i = 4 + addr_len; i >= 0; i--) {
00723 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
00724 outl(EE_ENB | dataval, ee_addr);
00725 eeprom_delay();
00726 outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
00727 eeprom_delay();
00728 }
00729 outl(EE_ENB, ee_addr);
00730
00731 for (i = 16; i > 0; i--) {
00732 outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
00733 eeprom_delay();
00734 retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
00735 outl(EE_ENB, ee_addr);
00736 eeprom_delay();
00737 }
00738
00739
00740 outl(EE_ENB & ~EE_CS, ee_addr);
00741 return retval;
00742 }
00743
00744
00745
00746
00747
00748 static void parse_eeprom(struct nic *nic)
00749 {
00750 unsigned char *p, *ee_data = tp->eeprom;
00751 int new_advertise = 0;
00752 int i;
00753
00754 #ifdef TULIP_DEBUG_WHERE
00755 whereami("parse_eeprom\n");
00756 #endif
00757
00758 tp->mtable = 0;
00759
00760
00761 for (i = 0; i < 8; i ++)
00762 if (ee_data[i] != ee_data[16+i])
00763 break;
00764 if (i >= 8) {
00765
00766 for (i = 0; eeprom_fixups[i].name; i++) {
00767 if (nic->node_addr[0] == eeprom_fixups[i].addr0
00768 && nic->node_addr[1] == eeprom_fixups[i].addr1
00769 && nic->node_addr[2] == eeprom_fixups[i].addr2) {
00770 if (nic->node_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
00771 i++;
00772 memcpy(ee_data + 26, eeprom_fixups[i].newtable,
00773 sizeof(eeprom_fixups[i].newtable));
00774 #ifdef TULIP_DEBUG
00775 printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",
00776 tp->nic_name, eeprom_fixups[i].name, tp->nic_name);
00777 #endif
00778 break;
00779 }
00780 }
00781 if (eeprom_fixups[i].name == NULL) {
00782 #ifdef TULIP_DEBUG
00783 printf("%s: Old style EEPROM with no media selection information.\n",
00784 tp->nic_name);
00785 #endif
00786 return;
00787 }
00788 }
00789
00790 if (ee_data[19] > 1) {
00791 #ifdef TULIP_DEBUG
00792 printf("%s: Multiport cards (%d ports) may not work correctly.\n",
00793 tp->nic_name, ee_data[19]);
00794 #endif
00795 }
00796
00797 p = (void *)ee_data + ee_data[27];
00798
00799 if (ee_data[27] == 0) {
00800 #ifdef TULIP_DEBUG
00801 if (tulip_debug > 1) {
00802 printf("%s: No Valid Media Table. ee_data[27] = %hhX\n",
00803 tp->nic_name, ee_data[27]);
00804 }
00805 #endif
00806 } else if (tp->chip_id == DC21041) {
00807 int media = get_u16(p);
00808 int count = p[2];
00809 p += 3;
00810
00811 printf("%s: 21041 Media table, default media %hX (%s).\n",
00812 tp->nic_name, media,
00813 media & 0x0800 ? "Autosense" : medianame[media & 15]);
00814 for (i = 0; i < count; i++) {
00815 unsigned char media_block = *p++;
00816 int media_code = media_block & MEDIA_MASK;
00817 if (media_block & 0x40)
00818 p += 6;
00819 switch(media_code) {
00820 case 0: new_advertise |= 0x0020; break;
00821 case 4: new_advertise |= 0x0040; break;
00822 }
00823 printf("%s: 21041 media #%d, %s.\n",
00824 tp->nic_name, media_code, medianame[media_code]);
00825 }
00826 } else {
00827 unsigned char csr12dir = 0;
00828 int count;
00829 struct mediatable *mtable;
00830 u16 media = get_u16(p);
00831
00832 p += 2;
00833 if (tp->flags & CSR12_IN_SROM)
00834 csr12dir = *p++;
00835 count = *p++;
00836
00837 tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];
00838
00839 mtable->defaultmedia = media;
00840 mtable->leafcount = count;
00841 mtable->csr12dir = csr12dir;
00842 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
00843 mtable->csr15dir = mtable->csr15val = 0;
00844
00845 printf("%s: EEPROM default media type %s.\n", tp->nic_name,
00846 media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
00847
00848 for (i = 0; i < count; i++) {
00849 struct medialeaf *leaf = &mtable->mleaf[i];
00850
00851 if ((p[0] & 0x80) == 0) {
00852 leaf->type = 0;
00853 leaf->media = p[0] & 0x3f;
00854 leaf->leafdata = p;
00855 if ((p[2] & 0x61) == 0x01)
00856 mtable->has_mii = 1;
00857 p += 4;
00858 } else {
00859 switch(leaf->type = p[1]) {
00860 case 5:
00861 mtable->has_reset = i;
00862 leaf->media = p[2] & 0x0f;
00863 break;
00864 case 1: case 3:
00865 mtable->has_mii = 1;
00866 leaf->media = 11;
00867 break;
00868 case 2:
00869 if ((p[2] & 0x3f) == 0) {
00870 u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;
00871 u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));
00872 mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;
00873 mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;
00874 }
00875
00876 case 0: case 4:
00877 mtable->has_nonmii = 1;
00878 leaf->media = p[2] & MEDIA_MASK;
00879 switch (leaf->media) {
00880 case 0: new_advertise |= 0x0020; break;
00881 case 4: new_advertise |= 0x0040; break;
00882 case 3: new_advertise |= 0x0080; break;
00883 case 5: new_advertise |= 0x0100; break;
00884 case 6: new_advertise |= 0x0200; break;
00885 }
00886 break;
00887 default:
00888 leaf->media = 19;
00889 }
00890 leaf->leafdata = p + 2;
00891 p += (p[0] & 0x3f) + 1;
00892 }
00893 #ifdef TULIP_DEBUG
00894 if (tulip_debug > 1 && leaf->media == 11) {
00895 unsigned char *bp = leaf->leafdata;
00896 printf("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",
00897 tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],
00898 bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
00899 }
00900 #endif
00901 printf("%s: Index #%d - Media %s (#%d) described "
00902 "by a %s (%d) block.\n",
00903 tp->nic_name, i, medianame[leaf->media], leaf->media,
00904 leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",
00905 leaf->type);
00906 }
00907 if (new_advertise)
00908 tp->sym_advertise = new_advertise;
00909 }
00910 }
00911
00912
00913
00914
00915
00916 static void tulip_init_ring(struct nic *nic __unused)
00917 {
00918 int i;
00919
00920 #ifdef TULIP_DEBUG_WHERE
00921 whereami("tulip_init_ring\n");
00922 #endif
00923
00924 tp->cur_rx = 0;
00925
00926 for (i = 0; i < RX_RING_SIZE; i++) {
00927 rx_ring[i].status = cpu_to_le32(0x80000000);
00928 rx_ring[i].length = cpu_to_le32(BUFLEN);
00929 rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);
00930 rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);
00931 }
00932
00933 rx_ring[i-1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
00934 rx_ring[i-1].buffer2 = virt_to_le32desc(&rx_ring[0]);
00935
00936
00937
00938
00939 tx_ring[0].status = 0x00000000;
00940 tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
00941 tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);
00942
00943
00944
00945 tx_ring[1].status = 0x00000000;
00946 tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);
00947 tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);
00948
00949
00950 tx_ring[1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
00951 }
00952
00953
00954 static void set_rx_mode(struct nic *nic __unused) {
00955 int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
00956
00957 tp->csr6 &= ~0x00D5;
00958
00959
00960 tp->csr6 |= AcceptAllMulticast;
00961 csr6 |= AcceptAllMulticast;
00962
00963 outl(csr6, ioaddr + CSR6);
00964
00965
00966
00967 }
00968
00969
00970
00971
00972 static void tulip_reset(struct nic *nic)
00973 {
00974 int i;
00975 unsigned long to;
00976
00977 #ifdef TULIP_DEBUG_WHERE
00978 whereami("tulip_reset\n");
00979 #endif
00980
00981
00982 outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
00983
00984
00985 if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) {
00986 outl(0x814C0000, ioaddr + CSR6);
00987 }
00988
00989
00990 outl(0x00000001, ioaddr + CSR0);
00991 tulip_wait(1);
00992
00993
00994 outl(tp->csr0, ioaddr + CSR0);
00995
00996
00997 tulip_wait(1);
00998
00999
01000 tulip_init_ring(nic);
01001
01002 if (tp->chip_id == PNIC2) {
01003 u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);
01004
01005 outl((nic->node_addr[5]<<8) + nic->node_addr[4] +
01006 (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),
01007 ioaddr + 0xB0);
01008 outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
01009 }
01010
01011
01012 if (tp->flags & MC_HASH_ONLY) {
01013 u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));
01014 u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));
01015
01016
01017 if (tp->flags & IS_ASIX) {
01018 outl(0, ioaddr + CSR13);
01019 outl(addr_low, ioaddr + CSR14);
01020 outl(1, ioaddr + CSR13);
01021 outl(addr_high, ioaddr + CSR14);
01022 outl(2, ioaddr + CSR13);
01023 outl(0, ioaddr + CSR14);
01024 outl(3, ioaddr + CSR13);
01025 outl(0, ioaddr + CSR14);
01026 } else if (tp->chip_id == COMET) {
01027 outl(addr_low, ioaddr + 0xA4);
01028 outl(addr_high, ioaddr + 0xA8);
01029 outl(0, ioaddr + 0xAC);
01030 outl(0, ioaddr + 0xB0);
01031 }
01032 } else {
01033
01034
01035 u32 tx_flags = 0x08000000 | 192;
01036
01037
01038
01039 for (i=0; i<192; i++)
01040 txb[i] = 0xFF;
01041 txb[0] = nic->node_addr[0];
01042 txb[1] = nic->node_addr[1];
01043 txb[4] = nic->node_addr[2];
01044 txb[5] = nic->node_addr[3];
01045 txb[8] = nic->node_addr[4];
01046 txb[9] = nic->node_addr[5];
01047
01048 tx_ring[0].length = cpu_to_le32(tx_flags);
01049 tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
01050 tx_ring[0].status = cpu_to_le32(0x80000000);
01051 }
01052
01053
01054 outl(virt_to_le32desc(&rx_ring[0]), ioaddr + CSR3);
01055 outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
01056
01057 init_media(nic);
01058
01059
01060 outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);
01061
01062
01063 if (!(tp->flags & MC_HASH_ONLY)) {
01064
01065 outl(tp->csr6 | 0x00002000, ioaddr + CSR6);
01066
01067 outl(0, ioaddr + CSR1);
01068
01069 to = currticks() + TX_TIME_OUT;
01070 while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
01071 ;
01072
01073 if (currticks() >= to) {
01074 printf ("%s: TX Setup Timeout.\n", tp->nic_name);
01075 }
01076 }
01077
01078 if (tp->chip_id == LC82C168)
01079 tulip_check_duplex(nic);
01080
01081 set_rx_mode(nic);
01082
01083
01084 outl(tp->csr6 | 0x00002002, ioaddr + CSR6);
01085 }
01086
01087
01088
01089
01090
01091 static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
01092 unsigned int s, const char *p)
01093 {
01094 u16 nstype;
01095 u32 to;
01096 u32 csr6 = inl(ioaddr + CSR6);
01097
01098 #ifdef TULIP_DEBUG_WHERE
01099 whereami("tulip_transmit\n");
01100 #endif
01101
01102
01103 outl(csr6 & ~0x00002000, ioaddr + CSR6);
01104
01105 memcpy(txb, d, ETH_ALEN);
01106 memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
01107 nstype = htons((u16) t);
01108 memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);
01109 memcpy(txb + ETH_HLEN, p, s);
01110
01111 s += ETH_HLEN;
01112 s &= 0x0FFF;
01113
01114
01115 while (s < ETH_ZLEN)
01116 txb[s++] = '\0';
01117
01118 #ifdef TULIP_DEBUG
01119 if (tulip_debug > 1)
01120 printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);
01121 #endif
01122
01123
01124
01125 tx_ring[0].length = cpu_to_le32(0x60000000 | s);
01126 tx_ring[0].status = cpu_to_le32(0x80000000);
01127
01128
01129 outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
01130
01131
01132 outl(csr6 | 0x00002000, ioaddr + CSR6);
01133
01134 outl(0, ioaddr + CSR1);
01135
01136 to = currticks() + TX_TIME_OUT;
01137 while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
01138 ;
01139
01140 if (currticks() >= to) {
01141 printf ("TX Timeout!\n");
01142 }
01143
01144
01145 outl(csr6 & ~0x00002000, ioaddr + CSR6);
01146 }
01147
01148
01149
01150
01151 static int tulip_poll(struct nic *nic, int retrieve)
01152 {
01153
01154 #ifdef TULIP_DEBUG_WHERE
01155 whereami("tulip_poll\n");
01156 #endif
01157
01158
01159 if (rx_ring[tp->cur_rx].status & 0x80000000)
01160 return 0;
01161
01162 if ( ! retrieve ) return 1;
01163
01164 #ifdef TULIP_DEBUG_WHERE
01165 whereami("tulip_poll got one\n");
01166 #endif
01167
01168 nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;
01169
01170
01171 if (rx_ring[tp->cur_rx].status & 0x00008000) {
01172
01173 rx_ring[tp->cur_rx].status = 0x80000000;
01174 tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
01175 return 0;
01176 }
01177
01178
01179 memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);
01180
01181
01182 rx_ring[tp->cur_rx].status = 0x80000000;
01183 tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
01184
01185 return 1;
01186 }
01187
01188
01189
01190
01191 static void tulip_disable ( struct nic *nic ) {
01192
01193 #ifdef TULIP_DEBUG_WHERE
01194 whereami("tulip_disable\n");
01195 #endif
01196
01197 tulip_reset(nic);
01198
01199
01200 outl(0x00000000, ioaddr + CSR7);
01201
01202
01203 outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
01204
01205
01206 inl(ioaddr + CSR8);
01207 }
01208
01209
01210
01211
01212 static void tulip_irq(struct nic *nic __unused, irq_action_t action __unused)
01213 {
01214 switch ( action ) {
01215 case DISABLE :
01216 break;
01217 case ENABLE :
01218 break;
01219 case FORCE :
01220 break;
01221 }
01222 }
01223
01224 static struct nic_operations tulip_operations = {
01225 .connect = dummy_connect,
01226 .poll = tulip_poll,
01227 .transmit = tulip_transmit,
01228 .irq = tulip_irq,
01229
01230 };
01231
01232
01233
01234
01235 static int tulip_probe ( struct nic *nic, struct pci_device *pci ) {
01236
01237 u32 i;
01238 u8 chip_rev;
01239 u8 ee_data[EEPROM_SIZE];
01240 unsigned short sum;
01241 int chip_idx;
01242 static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};
01243
01244 if (pci->ioaddr == 0)
01245 return 0;
01246
01247 ioaddr = pci->ioaddr;
01248 nic->ioaddr = pci->ioaddr & ~3;
01249 nic->irqno = 0;
01250
01251
01252 tp = &tulip_bss.tpx;
01253
01254 tp->vendor_id = pci->vendor;
01255 tp->dev_id = pci->device;
01256 tp->nic_name = pci->driver_name;
01257
01258 tp->if_port = 0;
01259 tp->default_port = 0;
01260
01261 adjust_pci_device(pci);
01262
01263
01264 outl(0x00000000, ioaddr + CSR7);
01265
01266
01267 outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
01268
01269
01270 inl(ioaddr + CSR8);
01271
01272 printf("\n");
01273 #ifdef TULIP_DEBUG_WHERE
01274 whereami("tulip_probe\n");
01275 #endif
01276
01277 #ifdef TULIP_DEBUG
01278 if (tulip_debug > 1)
01279 printf ("%s: Looking for Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
01280 tp->vendor, tp->dev_id);
01281 #endif
01282
01283
01284 i = 0;
01285 chip_idx = -1;
01286
01287 while (pci_id_tbl[i].name) {
01288 if ( (((u32) tp->dev_id << 16) | tp->vendor_id) ==
01289 (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {
01290 chip_idx = pci_id_tbl[i].drv_flags;
01291 break;
01292 }
01293 i++;
01294 }
01295
01296 if (chip_idx == -1) {
01297 printf ("%s: Unknown Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
01298 tp->vendor_id, tp->dev_id);
01299 return 0;
01300 }
01301
01302 tp->pci_id_idx = i;
01303 tp->flags = tulip_tbl[chip_idx].flags;
01304
01305 #ifdef TULIP_DEBUG
01306 if (tulip_debug > 1) {
01307 printf ("%s: tp->pci_id_idx == %d, name == %s\n", tp->nic_name,
01308 tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);
01309 printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx,
01310 tulip_tbl[chip_idx].chip_name);
01311 }
01312 #endif
01313
01314
01315
01316 if (tp->flags & HAS_PWRDWN)
01317 pci_write_config_dword(pci, 0x40, 0x00000000);
01318
01319 if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {
01320 printf("%s: The Tulip chip at %X is not functioning.\n",
01321 tp->nic_name, (unsigned int) ioaddr);
01322 return 0;
01323 }
01324
01325 pci_read_config_byte(pci, PCI_REVISION, &chip_rev);
01326
01327 printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,
01328 tulip_tbl[chip_idx].chip_name, chip_rev, (unsigned int) ioaddr);
01329 printf("%s: Vendor=%hX Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);
01330
01331 if (chip_idx == DC21041 && inl(ioaddr + CSR9) & 0x8000) {
01332 printf(" 21040 compatible mode.");
01333 chip_idx = DC21040;
01334 }
01335
01336 printf("\n");
01337
01338
01339 sum = 0;
01340 if (chip_idx == DC21040) {
01341 outl(0, ioaddr + CSR9);
01342 for (i = 0; i < ETH_ALEN; i++) {
01343 int value, boguscnt = 100000;
01344 do
01345 value = inl(ioaddr + CSR9);
01346 while (value < 0 && --boguscnt > 0);
01347 nic->node_addr[i] = value;
01348 sum += value & 0xff;
01349 }
01350 } else if (chip_idx == LC82C168) {
01351 for (i = 0; i < 3; i++) {
01352 int value, boguscnt = 100000;
01353 outl(0x600 | i, ioaddr + 0x98);
01354 do
01355 value = inl(ioaddr + CSR9);
01356 while (value < 0 && --boguscnt > 0);
01357 put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);
01358 sum += value & 0xffff;
01359 }
01360 } else if (chip_idx == COMET) {
01361
01362 put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);
01363 put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));
01364 for (i = 0; i < ETH_ALEN; i ++)
01365 sum += nic->node_addr[i];
01366 } else {
01367
01368 int sa_offset = 0;
01369 int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
01370
01371 for (i = 0; i < sizeof(ee_data)/2; i++)
01372 ((u16 *)ee_data)[i] =
01373 le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
01374
01375
01376
01377
01378 for (i = 0; i < 8; i ++)
01379 if (ee_data[i] != ee_data[16+i])
01380 sa_offset = 20;
01381 if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
01382 sa_offset = 2;
01383 }
01384 for (i = 0; i < ETH_ALEN; i ++) {
01385 nic->node_addr[i] = ee_data[i + sa_offset];
01386 sum += ee_data[i + sa_offset];
01387 }
01388 }
01389
01390 if ((nic->node_addr[0] == 0xA0 || nic->node_addr[0] == 0xC0)
01391 && nic->node_addr[1] == 0x00)
01392 for (i = 0; i < ETH_ALEN; i+=2) {
01393 char tmp = nic->node_addr[i];
01394 nic->node_addr[i] = nic->node_addr[i+1];
01395 nic->node_addr[i+1] = tmp;
01396 }
01397
01398 if (sum == 0 || sum == ETH_ALEN*0xff) {
01399 printf("%s: EEPROM not present!\n", tp->nic_name);
01400 for (i = 0; i < ETH_ALEN-1; i++)
01401 nic->node_addr[i] = last_phys_addr[i];
01402 nic->node_addr[i] = last_phys_addr[i] + 1;
01403 }
01404
01405 for (i = 0; i < ETH_ALEN; i++)
01406 last_phys_addr[i] = nic->node_addr[i];
01407
01408 DBG ( "%s: %s at ioaddr %hX\n", tp->nic_name, eth_ntoa ( nic->node_addr ),
01409 (unsigned int) ioaddr );
01410
01411 tp->chip_id = chip_idx;
01412 tp->revision = chip_rev;
01413 tp->csr0 = csr0;
01414
01415
01416
01417 if (chip_idx == DC21143 && chip_rev == 65)
01418 tp->csr0 &= ~0x01000000;
01419 else if (tp->flags & IS_ASIX)
01420 tp->csr0 |= 0x2000;
01421
01422 if (media_cap[tp->default_port] & MediaIsMII) {
01423 static const u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60,
01424 0x80, 0x100, 0x200 };
01425 tp->mii_advertise = media2advert[tp->default_port - 9];
01426 tp->mii_advertise |= (tp->flags & HAS_8023X);
01427 }
01428
01429
01430
01431 if (tp->flags & HAS_MEDIA_TABLE) {
01432 memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
01433 parse_eeprom(nic);
01434 }
01435
01436 start_link(nic);
01437
01438
01439 tulip_reset(nic);
01440 nic->nic_op = &tulip_operations;
01441
01442
01443 tulip_wait(4*TICKS_PER_SEC);
01444
01445 return 1;
01446 }
01447
01448 static void start_link(struct nic *nic)
01449 {
01450 int i;
01451
01452 #ifdef TULIP_DEBUG_WHERE
01453 whereami("start_link\n");
01454 #endif
01455
01456 if ((tp->flags & ALWAYS_CHECK_MII) ||
01457 (tp->mtable && tp->mtable->has_mii) ||
01458 ( ! tp->mtable && (tp->flags & HAS_MII))) {
01459 unsigned int phy, phy_idx;
01460 if (tp->mtable && tp->mtable->has_mii) {
01461 for (i = 0; i < tp->mtable->leafcount; i++)
01462 if (tp->mtable->mleaf[i].media == 11) {
01463 tp->cur_index = i;
01464 tp->saved_if_port = tp->if_port;
01465 select_media(nic, 2);
01466 tp->if_port = tp->saved_if_port;
01467 break;
01468 }
01469 }
01470
01471
01472 for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
01473 phy++) {
01474 int mii_status = mdio_read(nic, phy, 1);
01475 if ((mii_status & 0x8301) == 0x8001 ||
01476 ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
01477 int mii_reg0 = mdio_read(nic, phy, 0);
01478 int mii_advert = mdio_read(nic, phy, 4);
01479 int to_advert;
01480
01481 if (tp->mii_advertise)
01482 to_advert = tp->mii_advertise;
01483 else if (tp->advertising[phy_idx])
01484 to_advert = tp->advertising[phy_idx];
01485 else
01486 tp->mii_advertise = to_advert = mii_advert;
01487
01488 tp->phys[phy_idx++] = phy;
01489 printf("%s: MII transceiver %d config %hX status %hX advertising %hX.\n",
01490 tp->nic_name, phy, mii_reg0, mii_status, mii_advert);
01491
01492 if (mii_advert != to_advert) {
01493 printf("%s: Advertising %hX on PHY %d previously advertising %hX.\n",
01494 tp->nic_name, to_advert, phy, mii_advert);
01495 mdio_write(nic, phy, 4, to_advert);
01496 }
01497
01498 mdio_write(nic, phy, 0, mii_reg0 |
01499 (tp->full_duplex ? 0x1100 : 0x1000) |
01500 (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
01501 }
01502 }
01503 tp->mii_cnt = phy_idx;
01504 if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
01505 printf("%s: ***WARNING***: No MII transceiver found!\n",
01506 tp->nic_name);
01507 tp->phys[0] = 1;
01508 }
01509 }
01510
01511
01512 switch (tp->chip_id) {
01513 case DC21040:
01514 outl(0x00000000, ioaddr + CSR13);
01515 outl(0x00000004, ioaddr + CSR13);
01516 break;
01517 case DC21041:
01518
01519 if (tp->sym_advertise == 0)
01520 tp->sym_advertise = 0x0061;
01521 outl(0x00000000, ioaddr + CSR13);
01522 outl(0xFFFFFFFF, ioaddr + CSR14);
01523 outl(0x00000008, ioaddr + CSR15);
01524 outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
01525 outl(0x0000EF01, ioaddr + CSR13);
01526 break;
01527 case DC21140: default:
01528 if (tp->mtable)
01529 outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
01530 break;
01531 case DC21142:
01532 case PNIC2:
01533 if (tp->mii_cnt || media_cap[tp->if_port] & MediaIsMII) {
01534 outl(0x82020000, ioaddr + CSR6);
01535 outl(0x0000, ioaddr + CSR13);
01536 outl(0x0000, ioaddr + CSR14);
01537 outl(0x820E0000, ioaddr + CSR6);
01538 } else
01539 nway_start(nic);
01540 break;
01541 case LC82C168:
01542 if ( ! tp->mii_cnt) {
01543 tp->nway = 1;
01544 tp->nwayset = 0;
01545 outl(0x00420000, ioaddr + CSR6);
01546 outl(0x30, ioaddr + CSR12);
01547 outl(0x0001F078, ioaddr + 0xB8);
01548 outl(0x0201F078, ioaddr + 0xB8);
01549 }
01550 break;
01551 case MX98713: case COMPEX9881:
01552 outl(0x00000000, ioaddr + CSR6);
01553 outl(0x000711C0, ioaddr + CSR14);
01554 outl(0x00000001, ioaddr + CSR13);
01555 break;
01556 case MX98715: case MX98725:
01557 outl(0x01a80000, ioaddr + CSR6);
01558 outl(0xFFFFFFFF, ioaddr + CSR14);
01559 outl(0x00001000, ioaddr + CSR12);
01560 break;
01561 case COMET:
01562
01563 break;
01564 }
01565 }
01566
01567 static void nway_start(struct nic *nic __unused)
01568 {
01569 int csr14 = ((tp->sym_advertise & 0x0780) << 9) |
01570 ((tp->sym_advertise&0x0020)<<1) | 0xffbf;
01571
01572 #ifdef TULIP_DEBUG_WHERE
01573 whereami("nway_start\n");
01574 #endif
01575
01576 tp->if_port = 0;
01577 tp->nway = tp->mediasense = 1;
01578 tp->nwayset = tp->lpar = 0;
01579 if (tp->chip_id == PNIC2) {
01580 tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
01581 return;
01582 }
01583 #ifdef TULIP_DEBUG
01584 if (tulip_debug > 1)
01585 printf("%s: Restarting internal NWay autonegotiation, %X.\n",
01586 tp->nic_name, csr14);
01587 #endif
01588 outl(0x0001, ioaddr + CSR13);
01589 outl(csr14, ioaddr + CSR14);
01590 tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
01591 outl(tp->csr6, ioaddr + CSR6);
01592 if (tp->mtable && tp->mtable->csr15dir) {
01593 outl(tp->mtable->csr15dir, ioaddr + CSR15);
01594 outl(tp->mtable->csr15val, ioaddr + CSR15);
01595 } else if (tp->chip_id != PNIC2)
01596 outw(0x0008, ioaddr + CSR15);
01597 if (tp->chip_id == DC21041)
01598 outl(0xEF01, ioaddr + CSR12);
01599 else
01600 outl(0x1301, ioaddr + CSR12);
01601 }
01602
01603 static void init_media(struct nic *nic)
01604 {
01605 int i;
01606
01607 #ifdef TULIP_DEBUG_WHERE
01608 whereami("init_media\n");
01609 #endif
01610
01611 tp->saved_if_port = tp->if_port;
01612 if (tp->if_port == 0)
01613 tp->if_port = tp->default_port;
01614
01615
01616 i = 0;
01617 if (tp->mtable == NULL)
01618 goto media_picked;
01619 if (tp->if_port) {
01620 int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 :
01621 (tp->if_port == 12 ? 0 : tp->if_port);
01622 for (i = 0; i < tp->mtable->leafcount; i++)
01623 if (tp->mtable->mleaf[i].media == looking_for) {
01624 printf("%s: Using user-specified media %s.\n",
01625 tp->nic_name, medianame[tp->if_port]);
01626 goto media_picked;
01627 }
01628 }
01629 if ((tp->mtable->defaultmedia & 0x0800) == 0) {
01630 int looking_for = tp->mtable->defaultmedia & 15;
01631 for (i = 0; i < tp->mtable->leafcount; i++)
01632 if (tp->mtable->mleaf[i].media == looking_for) {
01633 printf("%s: Using EEPROM-set media %s.\n",
01634 tp->nic_name, medianame[looking_for]);
01635 goto media_picked;
01636 }
01637 }
01638
01639 for (i = tp->mtable->leafcount - 1;
01640 (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
01641 ;
01642 media_picked:
01643
01644 tp->csr6 = 0;
01645 tp->cur_index = i;
01646 tp->nwayset = 0;
01647
01648 if (tp->if_port) {
01649 if (tp->chip_id == DC21143 && media_cap[tp->if_port] & MediaIsMII) {
01650
01651 outl(0x0000, ioaddr + CSR13);
01652 outl(0x0000, ioaddr + CSR14);
01653 outl(0x0008, ioaddr + CSR15);
01654 }
01655 select_media(nic, 1);
01656 return;
01657 }
01658 switch(tp->chip_id) {
01659 case DC21041:
01660
01661 nway_start(nic);
01662 break;
01663 case DC21142:
01664 if (tp->mii_cnt) {
01665 select_media(nic, 1);
01666 #ifdef TULIP_DEBUG
01667 if (tulip_debug > 1)
01668 printf("%s: Using MII transceiver %d, status %hX.\n",
01669 tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1));
01670 #endif
01671 outl(0x82020000, ioaddr + CSR6);
01672 tp->csr6 = 0x820E0000;
01673 tp->if_port = 11;
01674 outl(0x0000, ioaddr + CSR13);
01675 outl(0x0000, ioaddr + CSR14);
01676 } else
01677 nway_start(nic);
01678 break;
01679 case PNIC2:
01680 nway_start(nic);
01681 break;
01682 case LC82C168:
01683 if (tp->mii_cnt) {
01684 tp->if_port = 11;
01685 tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
01686 outl(0x0001, ioaddr + CSR15);
01687 } else if (inl(ioaddr + CSR5) & TPLnkPass)
01688 pnic_do_nway(nic);
01689 else {
01690
01691 outl(0x32, ioaddr + CSR12);
01692 tp->csr6 = 0x00420000;
01693 outl(0x0001B078, ioaddr + 0xB8);
01694 outl(0x0201B078, ioaddr + 0xB8);
01695 }
01696 break;
01697 case MX98713: case COMPEX9881:
01698 tp->if_port = 0;
01699 tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
01700 outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
01701 break;
01702 case MX98715: case MX98725:
01703
01704 tp->if_port = 0;
01705 tp->csr6 = 0x01a80200;
01706 outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
01707 outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
01708 break;
01709 case COMET:
01710
01711 outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
01712 tp->if_port = 0;
01713 tp->csr6 = 0x00040000;
01714 break;
01715 case AX88140: case AX88141:
01716 tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
01717 break;
01718 default:
01719 select_media(nic, 1);
01720 }
01721 }
01722
01723 static void pnic_do_nway(struct nic *nic __unused)
01724 {
01725 u32 phy_reg = inl(ioaddr + 0xB8);
01726 u32 new_csr6 = tp->csr6 & ~0x40C40200;
01727
01728 #ifdef TULIP_DEBUG_WHERE
01729 whereami("pnic_do_nway\n");
01730 #endif
01731
01732 if (phy_reg & 0x78000000) {
01733 if (phy_reg & 0x20000000) tp->if_port = 5;
01734 else if (phy_reg & 0x40000000) tp->if_port = 3;
01735 else if (phy_reg & 0x10000000) tp->if_port = 4;
01736 else if (phy_reg & 0x08000000) tp->if_port = 0;
01737 tp->nwayset = 1;
01738 new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000;
01739 outl(0x32 | (tp->if_port & 1), ioaddr + CSR12);
01740 if (tp->if_port & 1)
01741 outl(0x1F868, ioaddr + 0xB8);
01742 if (phy_reg & 0x30000000) {
01743 tp->full_duplex = 1;
01744 new_csr6 |= 0x00000200;
01745 }
01746 #ifdef TULIP_DEBUG
01747 if (tulip_debug > 1)
01748 printf("%s: PNIC autonegotiated status %X, %s.\n",
01749 tp->nic_name, phy_reg, medianame[tp->if_port]);
01750 #endif
01751 if (tp->csr6 != new_csr6) {
01752 tp->csr6 = new_csr6;
01753 outl(tp->csr6 | 0x0002, ioaddr + CSR6);
01754 outl(tp->csr6 | 0x2002, ioaddr + CSR6);
01755 }
01756 }
01757 }
01758
01759
01760 static void select_media(struct nic *nic, int startup)
01761 {
01762 struct mediatable *mtable = tp->mtable;
01763 u32 new_csr6;
01764 int i;
01765
01766 #ifdef TULIP_DEBUG_WHERE
01767 whereami("select_media\n");
01768 #endif
01769
01770 if (mtable) {
01771 struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
01772 unsigned char *p = mleaf->leafdata;
01773 switch (mleaf->type) {
01774 case 0:
01775 #ifdef TULIP_DEBUG
01776 if (tulip_debug > 1)
01777 printf("%s: Using a 21140 non-MII transceiver"
01778 " with control setting %hhX.\n",
01779 tp->nic_name, p[1]);
01780 #endif
01781 tp->if_port = p[0];
01782 if (startup)
01783 outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
01784 outl(p[1], ioaddr + CSR12);
01785 new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
01786 break;
01787 case 2: case 4: {
01788 u16 setup[5];
01789 u32 csr13val, csr14val, csr15dir, csr15val;
01790 for (i = 0; i < 5; i++)
01791 setup[i] = get_u16(&p[i*2 + 1]);
01792
01793 tp->if_port = p[0] & 15;
01794 if (media_cap[tp->if_port] & MediaAlwaysFD)
01795 tp->full_duplex = 1;
01796
01797 if (startup && mtable->has_reset) {
01798 struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
01799 unsigned char *rst = rleaf->leafdata;
01800 #ifdef TULIP_DEBUG
01801 if (tulip_debug > 1)
01802 printf("%s: Resetting the transceiver.\n",
01803 tp->nic_name);
01804 #endif
01805 for (i = 0; i < rst[0]; i++)
01806 outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
01807 }
01808 #ifdef TULIP_DEBUG
01809 if (tulip_debug > 1)
01810 printf("%s: 21143 non-MII %s transceiver control "
01811 "%hX/%hX.\n",
01812 tp->nic_name, medianame[tp->if_port], setup[0], setup[1]);
01813 #endif
01814 if (p[0] & 0x40) {
01815 csr13val = setup[0];
01816 csr14val = setup[1];
01817 csr15dir = (setup[3]<<16) | setup[2];
01818 csr15val = (setup[4]<<16) | setup[2];
01819 outl(0, ioaddr + CSR13);
01820 outl(csr14val, ioaddr + CSR14);
01821 outl(csr15dir, ioaddr + CSR15);
01822 outl(csr15val, ioaddr + CSR15);
01823 outl(csr13val, ioaddr + CSR13);
01824 } else {
01825 csr13val = 1;
01826 csr14val = 0x0003FF7F;
01827 csr15dir = (setup[0]<<16) | 0x0008;
01828 csr15val = (setup[1]<<16) | 0x0008;
01829 if (tp->if_port <= 4)
01830 csr14val = t21142_csr14[tp->if_port];
01831 if (startup) {
01832 outl(0, ioaddr + CSR13);
01833 outl(csr14val, ioaddr + CSR14);
01834 }
01835 outl(csr15dir, ioaddr + CSR15);
01836 outl(csr15val, ioaddr + CSR15);
01837 if (startup) outl(csr13val, ioaddr + CSR13);
01838 }
01839 #ifdef TULIP_DEBUG
01840 if (tulip_debug > 1)
01841 printf("%s: Setting CSR15 to %X/%X.\n",
01842 tp->nic_name, csr15dir, csr15val);
01843 #endif
01844 if (mleaf->type == 4)
01845 new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
01846 else
01847 new_csr6 = 0x82420000;
01848 break;
01849 }
01850 case 1: case 3: {
01851 int phy_num = p[0];
01852 int init_length = p[1];
01853 u16 *misc_info;
01854
01855 tp->if_port = 11;
01856 new_csr6 = 0x020E0000;
01857 if (mleaf->type == 3) {
01858 u16 *init_sequence = (u16*)(p+2);
01859 u16 *reset_sequence = &((u16*)(p+3))[init_length];
01860 int reset_length = p[2 + init_length*2];
01861 misc_info = reset_sequence + reset_length;
01862 if (startup)
01863 for (i = 0; i < reset_length; i++)
01864 outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
01865 for (i = 0; i < init_length; i++)
01866 outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
01867 } else {
01868 u8 *init_sequence = p + 2;
01869 u8 *reset_sequence = p + 3 + init_length;
01870 int reset_length = p[2 + init_length];
01871 misc_info = (u16*)(reset_sequence + reset_length);
01872 if (startup) {
01873 outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
01874 for (i = 0; i < reset_length; i++)
01875 outl(reset_sequence[i], ioaddr + CSR12);
01876 }
01877 for (i = 0; i < init_length; i++)
01878 outl(init_sequence[i], ioaddr + CSR12);
01879 }
01880 tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1;
01881 if (startup < 2) {
01882 if (tp->mii_advertise == 0)
01883 tp->mii_advertise = tp->advertising[phy_num];
01884 #ifdef TULIP_DEBUG
01885 if (tulip_debug > 1)
01886 printf("%s: Advertising %hX on MII %d.\n",
01887 tp->nic_name, tp->mii_advertise, tp->phys[phy_num]);
01888 #endif
01889 mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise);
01890 }
01891 break;
01892 }
01893 default:
01894 printf("%s: Invalid media table selection %d.\n",
01895 tp->nic_name, mleaf->type);
01896 new_csr6 = 0x020E0000;
01897 }
01898 #ifdef TULIP_DEBUG
01899 if (tulip_debug > 1)
01900 printf("%s: Using media type %s, CSR12 is %hhX.\n",
01901 tp->nic_name, medianame[tp->if_port],
01902 inl(ioaddr + CSR12) & 0xff);
01903 #endif
01904 } else if (tp->chip_id == DC21041) {
01905 int port = tp->if_port <= 4 ? tp->if_port : 0;
01906 #ifdef TULIP_DEBUG
01907 if (tulip_debug > 1)
01908 printf("%s: 21041 using media %s, CSR12 is %hX.\n",
01909 tp->nic_name, medianame[port == 3 ? 12: port],
01910 inl(ioaddr + CSR12));
01911 #endif
01912 outl(0x00000000, ioaddr + CSR13);
01913 outl(t21041_csr14[port], ioaddr + CSR14);
01914 outl(t21041_csr15[port], ioaddr + CSR15);
01915 outl(t21041_csr13[port], ioaddr + CSR13);
01916 new_csr6 = 0x80020000;
01917 } else if (tp->chip_id == LC82C168) {
01918 if (startup && ! tp->medialock)
01919 tp->if_port = tp->mii_cnt ? 11 : 0;
01920 #ifdef TULIP_DEBUG
01921 if (tulip_debug > 1)
01922 printf("%s: PNIC PHY status is %hX, media %s.\n",
01923 tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]);
01924 #endif
01925 if (tp->mii_cnt) {
01926 new_csr6 = 0x810C0000;
01927 outl(0x0001, ioaddr + CSR15);
01928 outl(0x0201B07A, ioaddr + 0xB8);
01929 } else if (startup) {
01930
01931 outl(0x32, ioaddr + CSR12);
01932 new_csr6 = 0x00420000;
01933 outl(0x0001B078, ioaddr + 0xB8);
01934 outl(0x0201B078, ioaddr + 0xB8);
01935 } else if (tp->if_port == 3 || tp->if_port == 5) {
01936 outl(0x33, ioaddr + CSR12);
01937 new_csr6 = 0x01860000;
01938
01939 outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
01940 } else {
01941 outl(0x32, ioaddr + CSR12);
01942 new_csr6 = 0x00420000;
01943 outl(0x1F078, ioaddr + 0xB8);
01944 }
01945 } else if (tp->chip_id == DC21040) {
01946
01947 #ifdef TULIP_DEBUG
01948 int csr12 = inl(ioaddr + CSR12);
01949 if (tulip_debug > 1)
01950 printf("%s: 21040 media type is %s, CSR12 is %hhX.\n",
01951 tp->nic_name, medianame[tp->if_port], csr12);
01952 #endif
01953 if (media_cap[tp->if_port] & MediaAlwaysFD)
01954 tp->full_duplex = 1;
01955 new_csr6 = 0x20000;
01956
01957 outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
01958 outl(0x00000000, ioaddr + CSR13);
01959 if (t21040_csr13[tp->if_port] & 8) {
01960 outl(0x0705, ioaddr + CSR14);
01961 outl(0x0006, ioaddr + CSR15);
01962 } else {
01963 outl(0xffff, ioaddr + CSR14);
01964 outl(0x0000, ioaddr + CSR15);
01965 }
01966 outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13);
01967 } else {
01968 if (tp->default_port == 0)
01969 tp->if_port = tp->mii_cnt ? 11 : 3;
01970 if (media_cap[tp->if_port] & MediaIsMII) {
01971 new_csr6 = 0x020E0000;
01972 } else if (media_cap[tp->if_port] & MediaIsFx) {
01973 new_csr6 = 0x028600000;
01974 } else
01975 new_csr6 = 0x038600000;
01976 #ifdef TULIP_DEBUG
01977 if (tulip_debug > 1)
01978 printf("%s: No media description table, assuming "
01979 "%s transceiver, CSR12 %hhX.\n",
01980 tp->nic_name, medianame[tp->if_port],
01981 inl(ioaddr + CSR12));
01982 #endif
01983 }
01984
01985 tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
01986 return;
01987 }
01988
01989
01990
01991
01992
01993
01994
01995 static int tulip_check_duplex(struct nic *nic)
01996 {
01997 unsigned int bmsr, lpa, negotiated, new_csr6;
01998
01999 bmsr = mdio_read(nic, tp->phys[0], 1);
02000 lpa = mdio_read(nic, tp->phys[0], 5);
02001
02002 #ifdef TULIP_DEBUG
02003 if (tulip_debug > 1)
02004 printf("%s: MII status %#x, Link partner report "
02005 "%#x.\n", tp->nic_name, bmsr, lpa);
02006 #endif
02007
02008 if (bmsr == 0xffff)
02009 return -2;
02010 if ((bmsr & 4) == 0) {
02011 int new_bmsr = mdio_read(nic, tp->phys[0], 1);
02012 if ((new_bmsr & 4) == 0) {
02013 #ifdef TULIP_DEBUG
02014 if (tulip_debug > 1)
02015 printf("%s: No link beat on the MII interface,"
02016 " status %#x.\n", tp->nic_name,
02017 new_bmsr);
02018 #endif
02019 return -1;
02020 }
02021 }
02022 tp->full_duplex = lpa & 0x140;
02023
02024 new_csr6 = tp->csr6;
02025 negotiated = lpa & tp->advertising[0];
02026
02027 if(negotiated & 0x380) new_csr6 &= ~0x400000;
02028 else new_csr6 |= 0x400000;
02029 if (tp->full_duplex) new_csr6 |= 0x200;
02030 else new_csr6 &= ~0x200;
02031
02032 if (new_csr6 != tp->csr6) {
02033 tp->csr6 = new_csr6;
02034
02035 #ifdef TULIP_DEBUG
02036 if (tulip_debug > 0)
02037 printf("%s: Setting %s-duplex based on MII"
02038 "#%d link partner capability of %#x.\n",
02039 tp->nic_name,
02040 tp->full_duplex ? "full" : "half",
02041 tp->phys[0], lpa);
02042 #endif
02043 return 1;
02044 }
02045
02046 return 0;
02047 }
02048
02049 static struct pci_device_id tulip_nics[] = {
02050 PCI_ROM(0x1011, 0x0002, "dc21040", "Digital Tulip", 0),
02051 PCI_ROM(0x1011, 0x0009, "ds21140", "Digital Tulip Fast", 0),
02052 PCI_ROM(0x1011, 0x0014, "dc21041", "Digital Tulip+", 0),
02053 PCI_ROM(0x1011, 0x0019, "ds21142", "Digital Tulip 21142", 0),
02054 PCI_ROM(0x10b7, 0x9300, "3csoho100b-tx","3ComSOHO100B-TX", 0),
02055 PCI_ROM(0x10b9, 0x5261, "ali1563", "ALi 1563 integrated ethernet", 0),
02056 PCI_ROM(0x10d9, 0x0512, "mx98713", "Macronix MX987x3", 0),
02057 PCI_ROM(0x10d9, 0x0531, "mx98715", "Macronix MX987x5", 0),
02058 PCI_ROM(0x1113, 0x1217, "mxic-98715", "Macronix MX987x5", 0),
02059 PCI_ROM(0x11ad, 0xc115, "lc82c115", "LinkSys LNE100TX", 0),
02060 PCI_ROM(0x11ad, 0x0002, "82c168", "Netgear FA310TX", 0),
02061 PCI_ROM(0x1282, 0x9100, "dm9100", "Davicom 9100", 0),
02062 PCI_ROM(0x1282, 0x9102, "dm9102", "Davicom 9102", 0),
02063 PCI_ROM(0x1282, 0x9009, "dm9009", "Davicom 9009", 0),
02064 PCI_ROM(0x1282, 0x9132, "dm9132", "Davicom 9132", 0),
02065 PCI_ROM(0x1317, 0x0985, "centaur-p", "ADMtek Centaur-P", 0),
02066 PCI_ROM(0x1317, 0x0981, "an981", "ADMtek AN981 Comet", 0),
02067 PCI_ROM(0x1113, 0x1216, "an983", "ADMTek AN983 Comet", 0),
02068 PCI_ROM(0x1317, 0x9511, "an983b", "ADMTek Comet 983b", 0),
02069 PCI_ROM(0x1317, 0x1985, "centaur-c", "ADMTek Centaur-C", 0),
02070 PCI_ROM(0x8086, 0x0039, "intel21145", "Intel Tulip", 0),
02071 PCI_ROM(0x125b, 0x1400, "ax88140", "ASIX AX88140", 0),
02072 PCI_ROM(0x11f6, 0x9881, "rl100tx", "Compex RL100-TX", 0),
02073 PCI_ROM(0x115d, 0x0003, "xircomtulip", "Xircom Tulip", 0),
02074 PCI_ROM(0x104a, 0x0981, "tulip-0981", "Tulip 0x104a 0x0981", 0),
02075 PCI_ROM(0x104a, 0x2774, "SGThomson-STE10100A", "Tulip 0x104a 0x2774", 0),
02076 PCI_ROM(0x1113, 0x9511, "tulip-9511", "Tulip 0x1113 0x9511", 0),
02077 PCI_ROM(0x1186, 0x1561, "tulip-1561", "Tulip 0x1186 0x1561", 0),
02078 PCI_ROM(0x1259, 0xa120, "tulip-a120", "Tulip 0x1259 0xa120", 0),
02079 PCI_ROM(0x13d1, 0xab02, "tulip-ab02", "Tulip 0x13d1 0xab02", 0),
02080 PCI_ROM(0x13d1, 0xab03, "tulip-ab03", "Tulip 0x13d1 0xab03", 0),
02081 PCI_ROM(0x13d1, 0xab08, "tulip-ab08", "Tulip 0x13d1 0xab08", 0),
02082 PCI_ROM(0x14f1, 0x1803, "lanfinity", "Conexant LANfinity", 0),
02083 PCI_ROM(0x1626, 0x8410, "tulip-8410", "Tulip 0x1626 0x8410", 0),
02084 PCI_ROM(0x1737, 0xab08, "tulip-1737-ab08","Tulip 0x1737 0xab08", 0),
02085 PCI_ROM(0x1737, 0xab09, "tulip-ab09", "Tulip 0x1737 0xab09", 0),
02086 };
02087
02088 PCI_DRIVER ( tulip_driver, tulip_nics, PCI_NO_CLASS );
02089
02090 DRIVER ( "Tulip", nic_driver, pci_driver, tulip_driver,
02091 tulip_probe, tulip_disable );
02092
02093
02094
02095
02096
02097
02098
02099