source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/net/sis190.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 26.8 KB
Line 
1/*
2   sis190.c: Silicon Integrated Systems SiS190 ethernet driver
3
4   Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
5   Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
6   Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
7
8   Modified for gPXE 2009 by Thomas Miletich <thomas.miletich@gmail.com>
9
10   Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
11   genuine driver.
12
13   This software may be used and distributed according to the terms of
14   the GNU General Public License (GPL), incorporated herein by reference.
15   Drivers based on or derived from this code fall under the GPL and must
16   retain the authorship, copyright and license notice.  This file is not
17   a complete program and may only be used when the entire operating
18   system is licensed under the GPL.
19
20   See the file COPYING in this distribution for more information.
21
22 */
23
24FILE_LICENCE ( GPL_ANY );
25
26#include "sis190.h"
27
28static struct pci_device_id sis190_pci_tbl[] = {
29        PCI_ROM (0x1039, 0x0190, "sis190", "sis190", 0),
30        PCI_ROM (0x1039, 0x0191, "sis191", "sis191", 0),
31};
32
33/******************************************************************************
34 *************** HACK to keep ISA bridge in the PCI device list ***************
35 ******************************************************************************/
36
37/* Some sis190 variants store the MAC address in the BIOS CMOS. To read it, we
38 * have to use a PCI to ISA bridge. To access the bridge we need a few things
39 * from it's struct pci_device. We fake the successful probe of a driver to
40 * keep the bridge's struct pci_device in the list of pci_devices.
41 * See details in sis190_get_mac_addr_from_apc().
42 */
43
44static struct pci_device_id sis190_isa_bridge_tbl[] = {
45        PCI_ID (0x1039, 0x0965, "", "", 0),
46        PCI_ID (0x1039, 0x0966, "", "", 0),
47        PCI_ID (0x1039, 0x0968, "", "", 0),
48};
49
50static int sis190_isa_bridge_probe(struct pci_device *pdev __unused,
51                                   const struct pci_device_id *ent __unused)
52{
53        return 0;
54}
55
56static void sis190_isa_bridge_remove(struct pci_device *pdev __unused)
57{
58        return;
59}
60
61struct pci_driver sis190_isa_bridge_driver __pci_driver = {
62        .ids            = sis190_isa_bridge_tbl,
63        .id_count       = (sizeof(sis190_isa_bridge_tbl) /
64                           sizeof(sis190_isa_bridge_tbl[0])),
65        .probe          = sis190_isa_bridge_probe,
66        .remove         = sis190_isa_bridge_remove,
67};
68
69/******************************************************************************
70 *********************************** </HACK> **********************************
71 ******************************************************************************/
72
73static const u32 sis190_intr_mask =
74        RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
75
76/*
77 * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
78 * The chips use a 64 element hash table based on the Ethernet CRC.
79 */
80static const int multicast_filter_limit = 32;
81
82static void __mdio_cmd(void *ioaddr, u32 ctl)
83{
84        unsigned int i;
85
86        SIS_W32(GMIIControl, ctl);
87
88        mdelay(1);
89
90        for (i = 0; i < 100; i++) {
91                if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
92                        break;
93                mdelay(1);
94        }
95
96        if (i > 99)
97                DBG("sis190: PHY command timed out !\n");
98}
99
100static void mdio_write(void *ioaddr, int phy_id, int reg, int val)
101{
102        __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
103                (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
104                (((u32) val) << EhnMIIdataShift));
105}
106
107static int mdio_read(void *ioaddr, int phy_id, int reg)
108{
109        __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
110                (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
111
112        return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
113}
114
115static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
116{
117        struct sis190_private *tp = netdev_priv(dev);
118
119        mdio_write(tp->mmio_addr, phy_id, reg, val);
120}
121
122static int __mdio_read(struct net_device *dev, int phy_id, int reg)
123{
124        struct sis190_private *tp = netdev_priv(dev);
125
126        return mdio_read(tp->mmio_addr, phy_id, reg);
127}
128
129static u16 mdio_read_latched(void *ioaddr, int phy_id, int reg)
130{
131        mdio_read(ioaddr, phy_id, reg);
132        return mdio_read(ioaddr, phy_id, reg);
133}
134
135static u16 sis190_read_eeprom(void *ioaddr, u32 reg)
136{
137        u16 data = 0xffff;
138        unsigned int i;
139
140        if (!(SIS_R32(ROMControl) & 0x0002))
141                return 0;
142
143        SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
144
145        for (i = 0; i < 200; i++) {
146                if (!(SIS_R32(ROMInterface) & EEREQ)) {
147                        data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
148                        break;
149                }
150                mdelay(1);
151        }
152
153        return data;
154}
155
156static void sis190_irq_mask_and_ack(void *ioaddr)
157{
158        SIS_W32(IntrMask, 0x00);
159        SIS_W32(IntrStatus, 0xffffffff);
160        SIS_PCI_COMMIT();
161}
162
163static void sis190_asic_down(void *ioaddr)
164{
165        /* Stop the chip's Tx and Rx DMA processes. */
166
167        SIS_W32(TxControl, 0x1a00);
168        SIS_W32(RxControl, 0x1a00);
169
170        sis190_irq_mask_and_ack(ioaddr);
171}
172
173static inline void sis190_mark_as_last_descriptor(struct RxDesc *desc)
174{
175        desc->size |= cpu_to_le32(RingEnd);
176}
177
178static inline void sis190_give_to_asic(struct RxDesc *desc)
179{
180        u32 eor = le32_to_cpu(desc->size) & RingEnd;
181
182        desc->PSize = 0x0;
183        desc->size = cpu_to_le32((RX_BUF_SIZE & RX_BUF_MASK) | eor);
184        wmb();
185        desc->status = cpu_to_le32(OWNbit | INTbit);
186}
187
188static inline void sis190_map_to_asic(struct RxDesc *desc, u32 mapping)
189{
190        desc->addr = cpu_to_le32(mapping);
191        sis190_give_to_asic(desc);
192}
193
194static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
195{
196        desc->PSize = 0x0;
197        desc->addr = cpu_to_le32(0xdeadbeef);
198        desc->size &= cpu_to_le32(RingEnd);
199        wmb();
200        desc->status = 0x0;
201}
202
203static struct io_buffer *sis190_alloc_rx_iob(struct RxDesc *desc)
204{
205        struct io_buffer *iob;
206
207        iob = alloc_iob(RX_BUF_SIZE);
208        if (iob) {
209                u32 mapping;
210
211                mapping = virt_to_bus(iob->data);
212                sis190_map_to_asic(desc, mapping);
213        } else {
214                DBG("sis190: alloc_iob failed\n");
215                sis190_make_unusable_by_asic(desc);
216        }
217
218        return iob;
219}
220
221static u32 sis190_rx_fill(struct sis190_private *tp, u32 start, u32 end)
222{
223        u32 cur;
224
225        for (cur = start; cur < end; cur++) {
226                unsigned int i = cur % NUM_RX_DESC;
227
228                if (tp->Rx_iobuf[i])
229                        continue;
230
231                tp->Rx_iobuf[i] = sis190_alloc_rx_iob(tp->RxDescRing + i);
232
233                if (!tp->Rx_iobuf[i])
234                        break;
235        }
236        return cur - start;
237}
238
239static inline int sis190_rx_pkt_err(u32 status)
240{
241#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
242
243        if ((status & CRCOK) && !(status & ErrMask))
244                return 0;
245
246        return -1;
247}
248
249static int sis190_process_rx(struct sis190_private *tp)
250{
251        u32 rx_left, cur_rx = tp->cur_rx;
252        u32 delta, count;
253
254        rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
255
256        for (; rx_left > 0; rx_left--, cur_rx++) {
257                unsigned int entry = cur_rx % NUM_RX_DESC;
258                struct RxDesc *desc = tp->RxDescRing + entry;
259                u32 status;
260
261                if (le32_to_cpu(desc->status) & OWNbit)
262                        break;
263
264                status = le32_to_cpu(desc->PSize);
265
266                if (sis190_rx_pkt_err(status) < 0) {
267                        sis190_give_to_asic(desc);
268                } else {
269                        struct io_buffer *iob = tp->Rx_iobuf[entry];
270                        unsigned int pkt_size = (status & RxSizeMask) - 4;
271
272                        if (pkt_size > RX_BUF_SIZE) {
273                                DBG("sis190: (frag) status = %08x.\n", status);
274                                sis190_give_to_asic(desc);
275                                continue;
276                        }
277
278                        sis190_make_unusable_by_asic(desc);
279
280                        iob_put(iob, pkt_size);
281
282                        DBG2("sis190: received packet. len: %d\n", pkt_size);
283                        netdev_rx(tp->dev, iob);
284                        DBGIO_HD(iob->data, 60);
285                        tp->Rx_iobuf[entry] = NULL;
286                }
287        }
288        count = cur_rx - tp->cur_rx;
289        tp->cur_rx = cur_rx;
290
291        delta = sis190_rx_fill(tp, tp->dirty_rx, tp->cur_rx);
292        if (!delta && count)
293                DBG("sis190: no Rx buffer allocated.\n");
294        tp->dirty_rx += delta;
295
296        if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx))
297                DBG("sis190: Rx buffers exhausted.\n");
298
299        return count;
300}
301
302static inline int sis190_tx_pkt_err(u32 status)
303{
304#define TxErrMask (WND | TABRT | FIFO | LINK)
305
306        if (!(status & TxErrMask))
307                return 0;
308
309        return -1;
310}
311
312static void sis190_process_tx(struct sis190_private *tp)
313{
314        u32 pending, dirty_tx = tp->dirty_tx;
315
316        pending = tp->cur_tx - dirty_tx;
317
318        for (; pending; pending--, dirty_tx++) {
319                unsigned int entry = dirty_tx % NUM_TX_DESC;
320                struct TxDesc *txd = tp->TxDescRing + entry;
321                u32 status = le32_to_cpu(txd->status);
322                struct io_buffer *iob;
323
324                if (status & OWNbit)
325                        break;
326
327                iob = tp->Tx_iobuf[entry];
328
329                if (!iob)
330                        break;
331
332                if (sis190_tx_pkt_err(status) == 0) {
333                        DBG2("sis190: Transmitted packet: %#08x\n", status);
334                        netdev_tx_complete(tp->dev, iob);
335                } else {
336                        DBG("sis190: Transmit error: %#08x\n", status);
337                        netdev_tx_complete_err(tp->dev, iob, -EINVAL);
338                }
339
340                tp->Tx_iobuf[entry] = NULL;
341        }
342
343        if (tp->dirty_tx != dirty_tx)
344                tp->dirty_tx = dirty_tx;
345}
346
347/*
348 * The interrupt handler does all of the Rx thread work and cleans up after
349 * the Tx thread.
350 */
351static void sis190_poll(struct net_device *dev)
352{
353        struct sis190_private *tp = netdev_priv(dev);
354        void  *ioaddr = tp->mmio_addr;
355        u32 status;
356
357        status = SIS_R32(IntrStatus);
358
359        if ((status == 0xffffffff) || !status)
360                return;
361
362        SIS_W32(IntrStatus, status);
363
364        /* sis190_phy_task() needs to be called in event of a LinkChange and
365         * after auto-negotiation is finished. Finishing auto-neg won't generate
366         * any indication, hence we call it every time if the link is bad. */
367        if ((status & LinkChange) || !netdev_link_ok(dev))
368                sis190_phy_task(tp);
369
370        if (status & RxQInt)
371                sis190_process_rx(tp);
372
373        if (status & TxQ0Int)
374                sis190_process_tx(tp);
375}
376
377static inline void sis190_init_ring_indexes(struct sis190_private *tp)
378{
379        tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
380}
381
382static int sis190_init_ring(struct net_device *dev)
383{
384        struct sis190_private *tp = netdev_priv(dev);
385
386        sis190_init_ring_indexes(tp);
387
388        memset(tp->Tx_iobuf, 0, NUM_TX_DESC * sizeof(struct io_buffer *));
389        memset(tp->Rx_iobuf, 0, NUM_RX_DESC * sizeof(struct io_buffer *));
390
391        if (sis190_rx_fill(tp, 0, NUM_RX_DESC) != NUM_RX_DESC)
392                goto err;
393
394        sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
395
396        return 0;
397
398err:
399        sis190_free(dev);
400        return -ENOMEM;
401}
402
403static void sis190_set_rx_mode(struct net_device *dev)
404{
405        struct sis190_private *tp = netdev_priv(dev);
406        void *ioaddr = tp->mmio_addr;
407        u32 mc_filter[2];       /* Multicast hash filter */
408        u16 rx_mode;
409
410        rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
411        mc_filter[1] = mc_filter[0] = 0xffffffff;
412
413        SIS_W16(RxMacControl, rx_mode | 0x2);
414        SIS_W32(RxHashTable, mc_filter[0]);
415        SIS_W32(RxHashTable + 4, mc_filter[1]);
416
417}
418
419static void sis190_soft_reset(void  *ioaddr)
420{
421        SIS_W32(IntrControl, 0x8000);
422        SIS_PCI_COMMIT();
423        SIS_W32(IntrControl, 0x0);
424        sis190_asic_down(ioaddr);
425}
426
427static void sis190_hw_start(struct net_device *dev)
428{
429        struct sis190_private *tp = netdev_priv(dev);
430        void *ioaddr = tp->mmio_addr;
431
432        sis190_soft_reset(ioaddr);
433
434        SIS_W32(TxDescStartAddr, tp->tx_dma);
435        SIS_W32(RxDescStartAddr, tp->rx_dma);
436
437        SIS_W32(IntrStatus, 0xffffffff);
438        SIS_W32(IntrMask, 0x0);
439        SIS_W32(GMIIControl, 0x0);
440        SIS_W32(TxMacControl, 0x60);
441        SIS_W16(RxMacControl, 0x02);
442        SIS_W32(RxHashTable, 0x0);
443        SIS_W32(0x6c, 0x0);
444        SIS_W32(RxWolCtrl, 0x0);
445        SIS_W32(RxWolData, 0x0);
446
447        SIS_PCI_COMMIT();
448
449        sis190_set_rx_mode(dev);
450
451        SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
452        SIS_W32(RxControl, 0x1a1d);
453}
454
455static void sis190_phy_task(struct sis190_private *tp)
456{
457        struct net_device *dev = tp->dev;
458        void *ioaddr = tp->mmio_addr;
459        int phy_id = tp->mii_if.phy_id;
460        int cnt = 0;
461        u16 val;
462
463        val = mdio_read(ioaddr, phy_id, MII_BMCR);
464
465        /* 100ms timeout is completely arbitrary. I have no datasheet to
466         * check whether that's a sensible value or not.
467         */
468        while ((val & BMCR_RESET) && (cnt < 100)) {
469                val = mdio_read(ioaddr, phy_id, MII_BMCR);
470                mdelay(1);
471                cnt++;
472        }
473
474        if (cnt > 99) {
475                DBG("sis190: BMCR_RESET timeout\n");
476                return;
477        }
478
479        if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
480                     BMSR_ANEGCOMPLETE)) {
481                DBG("sis190: auto-negotiating...\n");
482                netdev_link_down(dev);
483        } else {
484                /* Rejoice ! */
485                struct {
486                        int val;
487                        u32 ctl;
488                        const char *msg;
489                } reg31[] = {
490                        { LPA_1000FULL, 0x07000c00 | 0x00001000,
491                                "1000 Mbps Full Duplex" },
492                        { LPA_1000HALF, 0x07000c00,
493                                "1000 Mbps Half Duplex" },
494                        { LPA_100FULL, 0x04000800 | 0x00001000,
495                                "100 Mbps Full Duplex" },
496                        { LPA_100HALF, 0x04000800,
497                                "100 Mbps Half Duplex" },
498                        { LPA_10FULL, 0x04000400 | 0x00001000,
499                                "10 Mbps Full Duplex" },
500                        { LPA_10HALF, 0x04000400,
501                                "10 Mbps Half Duplex" },
502                        { 0, 0x04000400, "unknown" }
503                }, *p = NULL;
504                u16 adv, autoexp, gigadv, gigrec;
505
506                val = mdio_read(ioaddr, phy_id, 0x1f);
507
508                val = mdio_read(ioaddr, phy_id, MII_LPA);
509                adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
510
511                autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION);
512
513                if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) {
514                        /* check for gigabit speed */
515                        gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000);
516                        gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000);
517                        val = (gigadv & (gigrec >> 2));
518                        if (val & ADVERTISE_1000FULL)
519                                p = reg31;
520                        else if (val & ADVERTISE_1000HALF)
521                                p = reg31 + 1;
522                }
523
524                if (!p) {
525                        val &= adv;
526
527                        for (p = reg31; p->val; p++) {
528                                if ((val & p->val) == p->val)
529                                        break;
530                        }
531                }
532
533                p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
534
535                if ((tp->features & F_HAS_RGMII) &&
536                    (tp->features & F_PHY_BCM5461)) {
537                        // Set Tx Delay in RGMII mode.
538                        mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
539                        udelay(200);
540                        mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
541                        p->ctl |= 0x03000000;
542                }
543
544                SIS_W32(StationControl, p->ctl);
545
546                if (tp->features & F_HAS_RGMII) {
547                        SIS_W32(RGDelay, 0x0441);
548                        SIS_W32(RGDelay, 0x0440);
549                }
550
551                DBG("sis190: link on %s mode.\n", p->msg);
552                netdev_link_up(dev);
553        }
554}
555
556static int sis190_open(struct net_device *dev)
557{
558        struct sis190_private *tp = netdev_priv(dev);
559        int rc;
560
561        /* Allocate TX ring */
562        tp->TxDescRing = malloc_dma(TX_RING_BYTES, RING_ALIGNMENT);
563        if (!tp->TxDescRing) {
564                DBG("sis190: TX ring allocation failed\n");
565                rc = -ENOMEM;
566                goto out;
567        }
568        tp->tx_dma = cpu_to_le32(virt_to_bus(tp->TxDescRing));
569
570        /* Allocate RX ring */
571        tp->RxDescRing = malloc_dma(RX_RING_BYTES, RING_ALIGNMENT);
572        if (!tp->RxDescRing) {
573                DBG("sis190: RX ring allocation failed\n");
574                rc = -ENOMEM;
575                goto error;
576        }
577        tp->rx_dma = cpu_to_le32(virt_to_bus(tp->RxDescRing));
578
579        rc = sis190_init_ring(dev);
580        if (rc < 0)
581                goto error;
582
583        /* init rx filter, also program MAC address to card */
584        sis190_init_rxfilter(dev);
585
586        sis190_hw_start(dev);
587out:
588        return rc;
589
590error:
591        sis190_free(dev);
592        goto out;
593}
594
595static void sis190_down(struct net_device *dev)
596{
597        struct sis190_private *tp = netdev_priv(dev);
598        void  *ioaddr = tp->mmio_addr;
599
600        do {
601                sis190_asic_down(ioaddr);
602        } while (SIS_R32(IntrMask));
603}
604
605static void sis190_free(struct net_device *dev)
606{
607        struct sis190_private *tp = netdev_priv(dev);
608        int i;
609
610        free_dma(tp->TxDescRing, TX_RING_BYTES);
611        free_dma(tp->RxDescRing, RX_RING_BYTES);
612
613        tp->TxDescRing = NULL;
614        tp->RxDescRing = NULL;
615
616        tp->tx_dma = 0;
617        tp->rx_dma = 0;
618
619        tp->cur_tx = tp->dirty_tx = 0;
620        tp->cur_rx = tp->dirty_rx = 0;
621
622        for (i = 0; i < NUM_RX_DESC; i++) {
623                free_iob(tp->Rx_iobuf[i]);
624                tp->Rx_iobuf[i] = NULL;
625        }
626
627        /* tx io_buffers aren't owned by the driver, so don't free them */
628        for(i = 0; i < NUM_TX_DESC; i++)
629                tp->Tx_iobuf[i] = NULL;
630}
631
632static void sis190_close(struct net_device *dev)
633{
634        sis190_down(dev);
635        sis190_free(dev);
636}
637
638static int sis190_transmit(struct net_device *dev, struct io_buffer *iob)
639{
640        struct sis190_private *tp = netdev_priv(dev);
641        void  *ioaddr = tp->mmio_addr;
642        u32 len, entry;
643        struct TxDesc *desc;
644
645        len = iob_len(iob);
646        if (len < ETH_ZLEN) {
647                iob_pad(iob, ETH_ZLEN);
648                len = ETH_ZLEN;
649        }
650
651        entry = tp->cur_tx % NUM_TX_DESC;
652        desc = tp->TxDescRing + entry;
653
654        if (le32_to_cpu(desc->status) & OWNbit) {
655                DBG("sis190: Tx Ring full\n");
656                return -EINVAL;
657        }
658
659        tp->Tx_iobuf[entry] = iob;
660
661        desc->PSize = cpu_to_le32(len);
662        desc->addr = cpu_to_le32(virt_to_bus(iob->data));
663
664        desc->size = cpu_to_le32(len);
665        if (entry == (NUM_TX_DESC - 1))
666                desc->size |= cpu_to_le32(RingEnd);
667
668        wmb();
669
670        desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
671
672        tp->cur_tx++;
673
674        SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
675
676        return 0;
677}
678
679static void sis190_free_phy(struct list_head *first_phy)
680{
681        struct sis190_phy *cur, *next;
682
683        list_for_each_entry_safe(cur, next, first_phy, list) {
684                free(cur);
685        }
686}
687
688/**
689 *      sis190_default_phy - Select default PHY for sis190 mac.
690 *      @dev: the net device to probe for
691 *
692 *      Select first detected PHY with link as default.
693 *      If no one is link on, select PHY whose types is HOME as default.
694 *      If HOME doesn't exist, select LAN.
695 */
696static u16 sis190_default_phy(struct sis190_private *tp)
697{
698        struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
699        struct mii_if_info *mii_if = &tp->mii_if;
700        void  *ioaddr = tp->mmio_addr;
701        u16 status;
702
703        phy_home = phy_default = phy_lan = NULL;
704
705        list_for_each_entry(phy, &tp->first_phy, list) {
706                status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
707
708                // Link ON & Not select default PHY & not ghost PHY.
709                if ((status & BMSR_LSTATUS) &&
710                    !phy_default &&
711                    (phy->type != UNKNOWN)) {
712                        phy_default = phy;
713                } else {
714                        status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
715                        mdio_write(ioaddr, phy->phy_id, MII_BMCR,
716                                   status | BMCR_ANENABLE | BMCR_ISOLATE);
717                        if (phy->type == HOME)
718                                phy_home = phy;
719                        else if (phy->type == LAN)
720                                phy_lan = phy;
721                }
722        }
723
724        if (!phy_default) {
725                if (phy_home)
726                        phy_default = phy_home;
727                else if (phy_lan)
728                        phy_default = phy_lan;
729                else
730                        phy_default = list_entry(&tp->first_phy,
731                                                 struct sis190_phy, list);
732        }
733
734        if (mii_if->phy_id != phy_default->phy_id) {
735                mii_if->phy_id = phy_default->phy_id;
736                DBG("sis190: Using transceiver at address %d as default.\n",
737                     mii_if->phy_id);
738        }
739
740        status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
741        status &= (~BMCR_ISOLATE);
742
743        mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
744        status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
745
746        return status;
747}
748
749static void sis190_init_phy(struct sis190_private *tp,
750                            struct sis190_phy *phy, unsigned int phy_id,
751                            u16 mii_status)
752{
753        void *ioaddr = tp->mmio_addr;
754        struct mii_chip_info *p;
755
756        INIT_LIST_HEAD(&phy->list);
757        phy->status = mii_status;
758        phy->phy_id = phy_id;
759
760        phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
761        phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
762
763        for (p = mii_chip_table; p->type; p++) {
764                if ((p->id[0] == phy->id[0]) &&
765                    (p->id[1] == (phy->id[1] & 0xfff0))) {
766                        break;
767                }
768        }
769
770        if (p->id[1]) {
771                phy->type = (p->type == MIX) ?
772                        ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
773                                LAN : HOME) : p->type;
774                tp->features |= p->feature;
775
776                DBG("sis190: %s transceiver at address %d.\n", p->name, phy_id);
777        } else {
778                phy->type = UNKNOWN;
779
780                DBG("sis190: unknown PHY 0x%x:0x%x transceiver at address %d\n",
781                    phy->id[0], (phy->id[1] & 0xfff0), phy_id);
782        }
783}
784
785static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
786{
787        if (tp->features & F_PHY_88E1111) {
788                void *ioaddr = tp->mmio_addr;
789                int phy_id = tp->mii_if.phy_id;
790                u16 reg[2][2] = {
791                        { 0x808b, 0x0ce1 },
792                        { 0x808f, 0x0c60 }
793                }, *p;
794
795                p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
796
797                mdio_write(ioaddr, phy_id, 0x1b, p[0]);
798                udelay(200);
799                mdio_write(ioaddr, phy_id, 0x14, p[1]);
800                udelay(200);
801        }
802}
803
804/**
805 *      sis190_mii_probe - Probe MII PHY for sis190
806 *      @dev: the net device to probe for
807 *
808 *      Search for total of 32 possible mii phy addresses.
809 *      Identify and set current phy if found one,
810 *      return error if it failed to found.
811 */
812static int sis190_mii_probe(struct net_device *dev)
813{
814        struct sis190_private *tp = netdev_priv(dev);
815        struct mii_if_info *mii_if = &tp->mii_if;
816        void *ioaddr = tp->mmio_addr;
817        int phy_id;
818        int rc = 0;
819
820        INIT_LIST_HEAD(&tp->first_phy);
821
822        for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
823                struct sis190_phy *phy;
824                u16 status;
825
826                status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
827
828                // Try next mii if the current one is not accessible.
829                if (status == 0xffff || status == 0x0000)
830                        continue;
831
832                phy = zalloc(sizeof(*phy));
833                if (!phy) {
834                        sis190_free_phy(&tp->first_phy);
835                        rc = -ENOMEM;
836                        goto out;
837                }
838
839                DBG("sis190: found PHY\n");
840
841                sis190_init_phy(tp, phy, phy_id, status);
842
843                list_add(&tp->first_phy, &phy->list);
844        }
845
846        if (list_empty(&tp->first_phy)) {
847                DBG("sis190: No MII transceivers found!\n");
848                rc = -EIO;
849                goto out;
850        }
851
852        /* Select default PHY for mac */
853        sis190_default_phy(tp);
854
855        sis190_mii_probe_88e1111_fixup(tp);
856
857        mii_if->dev = dev;
858        mii_if->mdio_read = __mdio_read;
859        mii_if->mdio_write = __mdio_write;
860        mii_if->phy_id_mask = PHY_ID_ANY;
861        mii_if->reg_num_mask = MII_REG_ANY;
862out:
863        return rc;
864}
865
866static void sis190_mii_remove(struct net_device *dev)
867{
868        struct sis190_private *tp = netdev_priv(dev);
869
870        sis190_free_phy(&tp->first_phy);
871}
872
873static int sis190_init_board(struct pci_device *pdev, struct net_device **netdev)
874{
875        struct sis190_private *tp;
876        struct net_device *dev;
877        void *ioaddr;
878        int rc;
879
880        dev = alloc_etherdev(sizeof(*tp));
881        if (!dev) {
882                DBG("sis190: unable to alloc new etherdev\n");
883                rc = -ENOMEM;
884                goto err;
885        }
886
887        dev->dev = &pdev->dev;
888
889        tp = netdev_priv(dev);
890        memset(tp, 0, sizeof(*tp));
891
892        tp->dev = dev;
893
894        adjust_pci_device(pdev);
895
896        ioaddr = ioremap(pdev->membase, SIS190_REGS_SIZE);
897        if (!ioaddr) {
898                DBG("sis190: cannot remap MMIO, aborting\n");
899                rc = -EIO;
900                goto err;
901        }
902
903        tp->pci_device = pdev;
904        tp->mmio_addr = ioaddr;
905
906        sis190_irq_mask_and_ack(ioaddr);
907
908        sis190_soft_reset(ioaddr);
909
910        *netdev = dev;
911
912        return 0;
913
914err:
915        return rc;
916}
917
918static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
919{
920        tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
921}
922
923static int sis190_get_mac_addr_from_eeprom(struct pci_device *pdev __unused,
924                                                     struct net_device *dev)
925{
926        struct sis190_private *tp = netdev_priv(dev);
927        void *ioaddr = tp->mmio_addr;
928        u16 sig;
929        int i;
930
931        DBG("sis190: Read MAC address from EEPROM\n");
932
933        /* Check to see if there is a sane EEPROM */
934        sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
935
936        if ((sig == 0xffff) || (sig == 0x0000)) {
937                DBG("sis190: Error EEPROM read.\n");
938                return -EIO;
939        }
940
941        /* Get MAC address from EEPROM */
942        for (i = 0; i < ETH_ALEN / 2; i++) {
943                u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
944
945                ((u16 *)dev->hw_addr)[i] = cpu_to_le16(w);
946        }
947
948        sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
949
950        return 0;
951}
952
953/**
954 *      sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model
955 *      @pdev: PCI device
956 *      @dev:  network device to get address for
957 *
958 *      SiS96x model, use APC CMOS RAM to store MAC address.
959 *      APC CMOS RAM is accessed through ISA bridge.
960 *      MAC address is read into @net_dev->dev_addr.
961 */
962static int sis190_get_mac_addr_from_apc(struct pci_device *pdev,
963                                        struct net_device *dev)
964{
965        struct sis190_private *tp = netdev_priv(dev);
966        struct pci_device *isa_bridge = NULL;
967        struct device *d;
968        u8 reg, tmp8;
969        unsigned int i;
970
971        DBG("sis190: Read MAC address from APC.\n");
972
973        list_for_each_entry(d, &(pdev->dev.siblings), siblings) {
974                unsigned int i;
975                isa_bridge = container_of(d, struct pci_device, dev);
976                for(i = 0; i < sis190_isa_bridge_driver.id_count; i++) {
977                        if(isa_bridge->vendor ==
978                             sis190_isa_bridge_driver.ids[i].vendor
979                             && isa_bridge->device ==
980                             sis190_isa_bridge_driver.ids[i].device) {
981                                DBG("sis190: ISA bridge found\n");
982                                break;
983                        } else {
984                                isa_bridge = NULL;
985                        }
986                }
987                if(isa_bridge)
988                        break;
989        }
990
991        if (!isa_bridge) {
992                DBG("sis190: Can not find ISA bridge.\n");
993                return -EIO;
994        }
995
996        /* Enable port 78h & 79h to access APC Registers. */
997        pci_read_config_byte(isa_bridge, 0x48, &tmp8);
998        reg = (tmp8 & ~0x02);
999        pci_write_config_byte(isa_bridge, 0x48, reg);
1000        udelay(50);
1001        pci_read_config_byte(isa_bridge, 0x48, &reg);
1002
1003        for (i = 0; i < ETH_ALEN; i++) {
1004                outb(0x9 + i, 0x78);
1005                dev->hw_addr[i] = inb(0x79);
1006        }
1007
1008        outb(0x12, 0x78);
1009        reg = inb(0x79);
1010
1011        sis190_set_rgmii(tp, reg);
1012
1013        /* Restore the value to ISA Bridge */
1014        pci_write_config_byte(isa_bridge, 0x48, tmp8);
1015
1016        return 0;
1017}
1018
1019/**
1020 *      sis190_init_rxfilter - Initialize the Rx filter
1021 *      @dev: network device to initialize
1022 *
1023 *      Set receive filter address to our MAC address
1024 *      and enable packet filtering.
1025 */
1026static inline void sis190_init_rxfilter(struct net_device *dev)
1027{
1028        struct sis190_private *tp = netdev_priv(dev);
1029        void *ioaddr = tp->mmio_addr;
1030        u16 ctl;
1031        int i;
1032
1033        ctl = SIS_R16(RxMacControl);
1034        /*
1035         * Disable packet filtering before setting filter.
1036         * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
1037         * only and followed by RxMacAddr (6 bytes). Strange. -- FR
1038         */
1039        SIS_W16(RxMacControl, ctl & ~0x0f00);
1040
1041        for (i = 0; i < ETH_ALEN; i++)
1042                SIS_W8(RxMacAddr + i, dev->ll_addr[i]);
1043
1044        SIS_W16(RxMacControl, ctl);
1045        SIS_PCI_COMMIT();
1046}
1047
1048static int sis190_get_mac_addr(struct pci_device *pdev,
1049                                         struct net_device *dev)
1050{
1051        int rc;
1052
1053        rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
1054        if (rc < 0) {
1055                u8 reg;
1056
1057                pci_read_config_byte(pdev, 0x73, &reg);
1058
1059                if (reg & 0x00000001)
1060                        rc = sis190_get_mac_addr_from_apc(pdev, dev);
1061        }
1062        return rc;
1063}
1064
1065static void sis190_set_speed_auto(struct net_device *dev)
1066{
1067        struct sis190_private *tp = netdev_priv(dev);
1068        void *ioaddr = tp->mmio_addr;
1069        int phy_id = tp->mii_if.phy_id;
1070        int val;
1071
1072        DBG("sis190: Enabling Auto-negotiation.\n");
1073
1074        val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
1075
1076        // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
1077        // unchanged.
1078        mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
1079                   ADVERTISE_100FULL | ADVERTISE_10FULL |
1080                   ADVERTISE_100HALF | ADVERTISE_10HALF);
1081
1082        // Enable 1000 Full Mode.
1083        mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
1084
1085        // Enable auto-negotiation and restart auto-negotiation.
1086        mdio_write(ioaddr, phy_id, MII_BMCR,
1087                   BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
1088}
1089
1090static void sis190_irq(struct net_device *dev, int enable)
1091{
1092        struct sis190_private *tp = netdev_priv(dev);
1093        void *ioaddr = tp->mmio_addr;
1094
1095        SIS_W32(IntrStatus, 0xffffffff);
1096
1097        if (enable == 0)
1098                SIS_W32(IntrMask, 0x00);
1099        else
1100                SIS_W32(IntrMask, sis190_intr_mask);
1101
1102        SIS_PCI_COMMIT();
1103}
1104
1105static struct net_device_operations sis190_netdev_ops = {
1106        .open = sis190_open,
1107        .close = sis190_close,
1108        .poll = sis190_poll,
1109        .transmit = sis190_transmit,
1110        .irq = sis190_irq,
1111};
1112
1113static int sis190_probe(struct pci_device *pdev,
1114                           const struct pci_device_id *ent __unused)
1115{
1116        struct sis190_private *tp;
1117        struct net_device *dev;
1118        void *ioaddr;
1119        int rc;
1120
1121        rc = sis190_init_board(pdev, &dev);
1122        if (rc < 0)
1123                goto out;
1124
1125        pci_set_drvdata(pdev, dev);
1126
1127        tp = netdev_priv(dev);
1128        ioaddr = tp->mmio_addr;
1129
1130        rc = sis190_get_mac_addr(pdev, dev);
1131        if (rc < 0)
1132                goto err;
1133
1134        rc = sis190_mii_probe(dev);
1135        if (rc < 0)
1136                goto err;
1137
1138        rc = register_netdev(dev);
1139        if (rc < 0)
1140                goto err;
1141
1142        sis190_set_speed_auto(dev);
1143        sis190_phy_task(tp);
1144
1145        netdev_init(dev, &sis190_netdev_ops);
1146        netdev_link_down(dev);
1147out:
1148        return rc;
1149
1150err:
1151        sis190_mii_remove(dev);
1152        iounmap(tp->mmio_addr);
1153        goto out;
1154}
1155
1156static void sis190_remove(struct pci_device *pdev)
1157{
1158        struct net_device *dev = pci_get_drvdata(pdev);
1159        struct sis190_private *tp = dev->priv;
1160        void *ioaddr = tp->mmio_addr;
1161
1162        sis190_mii_remove(dev);
1163
1164        /* shutdown chip, disable interrupts, etc */
1165        sis190_soft_reset(ioaddr);
1166
1167        iounmap(tp->mmio_addr);
1168
1169        unregister_netdev(dev);
1170        netdev_nullify(dev);
1171        netdev_put(dev);
1172}
1173
1174struct pci_driver sis190_pci_driver __pci_driver = {
1175        .ids            = sis190_pci_tbl,
1176        .id_count       = (sizeof(sis190_pci_tbl) / sizeof(sis190_pci_tbl[0])),
1177        .probe          = sis190_probe,
1178        .remove         = sis190_remove,
1179};
Note: See TracBrowser for help on using the repository browser.