2 * Linux device driver for
3 * Broadcom BCM47XX 10/100 Mbps Ethernet Controller
5 * Copyright 2006, Broadcom Corporation
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: et_linux.c,v 1.1.1.1 2007/03/20 12:22:00 roly Exp $
16 #define __UNDEF_NO_VERSION__
20 #include <linux/module.h>
25 #include <linux/types.h>
26 #include <linux/errno.h>
27 #include <linux/pci.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/delay.h>
34 #include <linux/string.h>
35 #include <linux/sockios.h>
37 #include <linux/ethtool.h>
38 #endif /* SIOCETHTOOL */
39 #include <linux/mii.h>
42 #include <asm/system.h>
45 #include <asm/pgtable.h>
46 #include <asm/uaccess.h>
49 #include <bcmendian.h>
51 #include <proto/ethernet.h>
52 #include <proto/vlan.h>
54 #include <bcmenetmib.h>
55 #include <bcmenetrxh.h>
56 #include <bcmenetphy.h>
63 typedef struct et_info
{
64 etc_info_t
*etc
; /* pointer to common os-independent data */
65 struct net_device
*dev
; /* backpoint to device */
66 struct pci_dev
*pdev
; /* backpoint to pci_dev */
67 void *osh
; /* pointer to os handle */
68 spinlock_t lock
; /* per-device perimeter lock */
69 struct sk_buff_head txq
; /* send queue */
70 void *regsva
; /* opaque chip registers virtual address */
71 struct timer_list timer
; /* one second watchdog timer */
72 struct net_device_stats stats
; /* stat counter reporting structure */
73 int events
; /* bit channel between isr and dpc */
74 struct tasklet_struct tasklet
; /* dpc tasklet */
75 struct et_info
*next
; /* pointer to next et_info_t in chain */
76 bool resched
; /* dpc was rescheduled */
79 static int et_found
= 0;
80 static et_info_t
*et_list
= NULL
;
83 #define DATAHIWAT 50 /* data msg txq hiwat mark */
85 #define ET_INFO(dev) (et_info_t*)((dev)->priv)
87 #define ET_LOCK(et) spin_lock_bh(&(et)->lock)
88 #define ET_UNLOCK(et) spin_unlock_bh(&(et)->lock)
90 #define INT_LOCK(flags) local_irq_save(flags)
91 #define INT_UNLOCK(flags) local_irq_restore(flags)
93 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5)
94 #error Linux version must be newer than 2.4.5
95 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) */
97 /* prototypes called by etc.c */
98 void et_init(et_info_t
*et
);
99 void et_reset(et_info_t
*et
);
100 void et_link_up(et_info_t
*et
);
101 void et_link_down(et_info_t
*et
);
102 void et_up(et_info_t
*et
);
103 void et_down(et_info_t
*et
, int reset
);
104 void et_dump(et_info_t
*et
, struct bcmstrbuf
*b
);
106 /* local prototypes */
107 static void et_free(et_info_t
*et
);
108 static int et_open(struct net_device
*dev
);
109 static int et_close(struct net_device
*dev
);
110 static int et_start(struct sk_buff
*skb
, struct net_device
*dev
);
111 static void et_sendnext(et_info_t
*et
);
112 static struct net_device_stats
*et_get_stats(struct net_device
*dev
);
113 static int et_set_mac_address(struct net_device
*dev
, void *addr
);
114 static void et_set_multicast_list(struct net_device
*dev
);
115 static void et_watchdog(ulong data
);
116 static int et_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
);
117 static irqreturn_t
et_isr(int irq
, void *dev_id
, struct pt_regs
*ptregs
);
118 static void et_dpc(ulong data
);
119 static void et_sendup(et_info_t
*et
, struct sk_buff
*skb
);
121 /* recognized PCI IDs */
122 static struct pci_device_id et_id_table
[] __devinitdata
= {
123 { vendor
: PCI_ANY_ID
,
125 subvendor
: PCI_ANY_ID
,
126 subdevice
: PCI_ANY_ID
,
127 class: PCI_CLASS_NETWORK_ETHERNET
<< 8,
128 class_mask
: 0xffff00,
133 MODULE_DEVICE_TABLE(pci
, et_id_table
);
137 et_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
139 struct net_device
*dev
;
146 ET_TRACE(("et%d: et_probe: bus %d slot %d func %d irq %d\n", unit
,
147 pdev
->bus
->number
, PCI_SLOT(pdev
->devfn
), PCI_FUNC(pdev
->devfn
), pdev
->irq
));
149 if (!etc_chipmatch(pdev
->vendor
, pdev
->device
))
152 osh
= osl_attach(pdev
, PCI_BUS
, FALSE
);
155 pci_set_master(pdev
);
156 pci_enable_device(pdev
);
158 if (!(dev
= (struct net_device
*) MALLOC(osh
, sizeof(struct net_device
)))) {
159 ET_ERROR(("et%d: et_probe: out of memory, malloced %d bytes\n", unit
,
164 bzero(dev
, sizeof(struct net_device
));
166 if (!init_etherdev(dev
, 0)) {
167 ET_ERROR(("et%d: et_probe: init_etherdev() failed\n", unit
));
168 MFREE(osh
, dev
, sizeof(struct net_device
));
173 /* allocate private info */
174 if ((et
= (et_info_t
*) MALLOC(osh
, sizeof(et_info_t
))) == NULL
) {
175 ET_ERROR(("et%d: et_probe: out of memory, malloced %d bytes\n", unit
,
177 MFREE(osh
, dev
, sizeof(et_info_t
));
181 bzero(et
, sizeof(et_info_t
));
182 dev
->priv
= (void*) et
;
186 pci_set_drvdata(pdev
, et
);
188 /* map chip registers (47xx: and sprom) */
189 dev
->base_addr
= pci_resource_start(pdev
, 0);
190 if ((et
->regsva
= ioremap_nocache(dev
->base_addr
, PCI_BAR0_WINSZ
)) == NULL
) {
191 ET_ERROR(("et%d: ioremap() failed\n", unit
));
195 spin_lock_init(&et
->lock
);
197 skb_queue_head_init(&et
->txq
);
199 /* common load-time initialization */
200 if ((et
->etc
= etc_attach((void*)et
, pdev
->vendor
, pdev
->device
, unit
, osh
, et
->regsva
)) ==
202 ET_ERROR(("et%d: etc_attach() failed\n", unit
));
206 bcopy(&et
->etc
->cur_etheraddr
, dev
->dev_addr
, ETHER_ADDR_LEN
);
208 /* init 1 second watchdog timer */
209 init_timer(&et
->timer
);
210 et
->timer
.data
= (ulong
)dev
;
211 et
->timer
.function
= et_watchdog
;
213 /* setup the bottom half handler */
214 tasklet_init(&et
->tasklet
, et_dpc
, (ulong
)et
);
216 /* register our interrupt handler */
217 if (request_irq(pdev
->irq
, et_isr
, SA_SHIRQ
, dev
->name
, et
)) {
218 ET_ERROR(("et%d: request_irq() failed\n", unit
));
221 dev
->irq
= pdev
->irq
;
223 /* add us to the global linked list */
227 /* print hello string */
228 (*et
->etc
->chops
->longname
)(et
->etc
->ch
, name
, sizeof(name
));
229 printf("%s: %s %s\n", dev
->name
, name
, EPI_VERSION_STR
);
231 /* lastly, enable our entry points */
233 dev
->stop
= et_close
;
234 dev
->hard_start_xmit
= et_start
;
235 dev
->get_stats
= et_get_stats
;
236 dev
->set_mac_address
= et_set_mac_address
;
237 dev
->set_multicast_list
= et_set_multicast_list
;
238 dev
->do_ioctl
= et_ioctl
;
240 if (register_netdev(dev
)) {
241 ET_ERROR(("et%d: register_netdev() failed\n", unit
));
254 et_suspend(struct pci_dev
*pdev
, u32 state
)
258 if ((et
= (et_info_t
*) pci_get_drvdata(pdev
))) {
259 netif_device_detach(et
->dev
);
269 et_resume(struct pci_dev
*pdev
)
273 if ((et
= (et_info_t
*) pci_get_drvdata(pdev
))) {
277 netif_device_attach(et
->dev
);
283 /* Compatibility routines */
284 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)
286 _et_suspend(struct pci_dev
*pdev
)
292 _et_resume(struct pci_dev
*pdev
)
296 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6) */
298 static void __devexit
299 et_remove(struct pci_dev
*pdev
)
303 if (!etc_chipmatch(pdev
->vendor
, pdev
->device
))
308 if ((et
= (et_info_t
*) pci_get_drvdata(pdev
))) {
310 pci_set_drvdata(pdev
, NULL
);
314 static struct pci_driver et_pci_driver
= {
317 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)
318 suspend
: _et_suspend
,
323 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6) */
324 remove
: __devexit_p(et_remove
),
325 id_table
: et_id_table
,
331 return pci_module_init(&et_pci_driver
);
337 pci_unregister_driver(&et_pci_driver
);
340 module_init(et_module_init
);
341 module_exit(et_module_exit
);
344 et_free(et_info_t
*et
)
352 ET_TRACE(("et: et_free\n"));
354 if (et
->dev
&& et
->dev
->irq
)
355 free_irq(et
->dev
->irq
, et
);
358 unregister_netdev(et
->dev
);
359 MFREE(et
->osh
, et
->dev
, sizeof(struct net_device
));
363 /* free common resources */
370 * unregister_netdev() calls get_stats() which may read chip registers
371 * so we cannot unmap the chip registers until after calling unregister_netdev() .
374 iounmap((void*)et
->regsva
);
378 /* remove us from the global linked list */
379 for (prev
= &et_list
; *prev
; prev
= &(*prev
)->next
)
386 MFREE(et
->osh
, et
, sizeof(et_info_t
));
388 ASSERT(MALLOCED(osh
) == 0);
394 et_open(struct net_device
*dev
)
400 ET_TRACE(("et%d: et_open\n", et
->etc
->unit
));
402 et
->etc
->promisc
= (dev
->flags
& IFF_PROMISC
)? TRUE
: FALSE
;
408 OLD_MOD_INC_USE_COUNT
;
414 et_close(struct net_device
*dev
)
420 ET_TRACE(("et%d: et_close\n", et
->etc
->unit
));
422 et
->etc
->promisc
= FALSE
;
428 OLD_MOD_DEC_USE_COUNT
;
434 * Yeah, queueing the packets on a tx queue instead of throwing them
435 * directly into the descriptor ring in the case of dma is kinda lame,
436 * but this results in a unified transmit path for both dma and pio
437 * and localizes/simplifies the netif_*_queue semantics, too.
440 et_start(struct sk_buff
*skb
, struct net_device
*dev
)
446 ET_TRACE(("et%d: et_start: len %d\n", et
->etc
->unit
, skb
->len
));
447 ET_LOG("et%d: et_start: len %d", et
->etc
->unit
, skb
->len
);
451 /* put it on the tx queue and call sendnext */
452 skb_queue_tail(&et
->txq
, skb
);
457 ET_LOG("et%d: et_start ret\n", et
->etc
->unit
, 0);
463 et_sendnext(et_info_t
*et
)
471 ET_TRACE(("et%d: et_sendnext\n", etc
->unit
));
472 ET_LOG("et%d: et_sendnext", etc
->unit
, 0);
474 /* dequeue and send each packet */
476 while (*etc
->txavail
> 0) {
478 while (etc
->pioactive
== NULL
) {
480 if ((skb
= skb_dequeue(&et
->txq
)) == NULL
)
483 ET_PRHDR("tx", (struct ether_header
*) skb
->data
, skb
->len
, etc
->unit
);
484 ET_PRPKT("txpkt", skb
->data
, skb
->len
, etc
->unit
);
486 /* Convert the packet. */
487 if ((p
= PKTFRMNATIVE(et
->osh
, skb
)) == NULL
) {
488 dev_kfree_skb_any(skb
);
492 (*etc
->chops
->tx
)(etc
->ch
, p
);
495 etc
->txbyte
+= skb
->len
;
498 /* stop the queue whenever txq fills */
499 if ((skb_queue_len(&et
->txq
) > DATAHIWAT
) && !netif_queue_stopped(et
->dev
))
500 netif_stop_queue(et
->dev
);
501 else if (netif_queue_stopped(et
->dev
) && (skb_queue_len(&et
->txq
) < (DATAHIWAT
/2))) {
502 netif_wake_queue(et
->dev
);
507 et_init(et_info_t
*et
)
509 ET_TRACE(("et%d: et_init\n", et
->etc
->unit
));
510 ET_LOG("et%d: et_init", et
->etc
->unit
, 0);
519 et_reset(et_info_t
*et
)
521 ET_TRACE(("et%d: et_reset\n", et
->etc
->unit
));
525 /* zap any pending dpc interrupt bits */
528 /* dpc will not be rescheduled */
542 ET_TRACE(("et%d: et_up\n", etc
->unit
));
546 /* schedule one second watchdog timer */
547 et
->timer
.expires
= jiffies
+ HZ
;
548 add_timer(&et
->timer
);
550 netif_start_queue(et
->dev
);
554 et_down(et_info_t
*et
, int reset
)
561 ET_TRACE(("et%d: et_down\n", etc
->unit
));
564 netif_stop_queue(et
->dev
);
566 /* stop watchdog timer */
567 del_timer(&et
->timer
);
569 etc_down(etc
, reset
);
572 while ((skb
= skb_dequeue(&et
->txq
)))
573 dev_kfree_skb_any(skb
);
577 tasklet_kill(&et
->tasklet
);
582 * These are interrupt on/off entry points. Disable interrupts
583 * during interrupt state transition.
586 et_intrson(et_info_t
*et
)
590 (*et
->etc
->chops
->intrson
)(et
->etc
->ch
);
595 et_watchdog(ulong data
)
599 et
= ET_INFO((struct net_device
*)data
);
603 etc_watchdog(et
->etc
);
605 /* reschedule one second watchdog timer */
606 et
->timer
.expires
= jiffies
+ HZ
;
607 add_timer(&et
->timer
);
615 et_ethtool(et_info_t
*et
, struct ethtool_cmd
*ecmd
)
619 struct ethtool_drvinfo
*info
;
625 ecmd
->supported
= (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
|
626 SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
|
628 ecmd
->advertising
= ADVERTISED_TP
;
629 ecmd
->advertising
|= (et
->etc
->advertise
& ADV_10HALF
) ?
630 ADVERTISED_10baseT_Half
: 0;
631 ecmd
->advertising
|= (et
->etc
->advertise
& ADV_10FULL
) ?
632 ADVERTISED_10baseT_Full
: 0;
633 ecmd
->advertising
|= (et
->etc
->advertise
& ADV_100HALF
) ?
634 ADVERTISED_100baseT_Half
: 0;
635 ecmd
->advertising
|= (et
->etc
->advertise
& ADV_100FULL
) ?
636 ADVERTISED_100baseT_Full
: 0;
637 if (et
->etc
->linkstate
) {
638 ecmd
->speed
= (et
->etc
->speed
== 100) ? SPEED_100
: SPEED_10
;
639 ecmd
->duplex
= (et
->etc
->duplex
== 1) ? DUPLEX_FULL
: DUPLEX_HALF
;
644 ecmd
->port
= PORT_TP
;
645 ecmd
->phy_address
= 0;
646 ecmd
->transceiver
= XCVR_INTERNAL
;
647 ecmd
->autoneg
= (et
->etc
->forcespeed
== ET_AUTO
) ? AUTONEG_ENABLE
: AUTONEG_DISABLE
;
652 if (!capable(CAP_NET_ADMIN
)) {
656 else if (ecmd
->speed
== SPEED_10
&& ecmd
->duplex
== DUPLEX_HALF
)
658 else if (ecmd
->speed
== SPEED_10
&& ecmd
->duplex
== DUPLEX_FULL
)
660 else if (ecmd
->speed
== SPEED_100
&& ecmd
->duplex
== DUPLEX_HALF
)
662 else if (ecmd
->speed
== SPEED_100
&& ecmd
->duplex
== DUPLEX_FULL
)
664 else if (ecmd
->autoneg
== AUTONEG_ENABLE
)
670 ret
= etc_ioctl(et
->etc
, ETCSPEED
, &speed
);
672 case ETHTOOL_GDRVINFO
:
673 info
= (struct ethtool_drvinfo
*)ecmd
;
674 bzero(info
, sizeof(struct ethtool_drvinfo
));
675 info
->cmd
= ETHTOOL_GDRVINFO
;
676 sprintf(info
->driver
, "et%d", et
->etc
->unit
);
677 strcpy(info
->version
, EPI_VERSION_STR
);
688 #endif /* SIOCETHTOOL */
691 et_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
)
698 struct mii_ioctl_data
*data
= (struct mii_ioctl_data
*)&ifr
->ifr_data
;
702 ET_TRACE(("et%d: et_ioctl: cmd 0x%x\n", et
->etc
->unit
, cmd
));
707 if (((struct ethtool_cmd
*)ifr
->ifr_data
)->cmd
== ETHTOOL_GDRVINFO
)
708 size
= sizeof(struct ethtool_drvinfo
);
710 size
= sizeof(struct ethtool_cmd
);
711 get
= TRUE
; set
= TRUE
;
713 #endif /* SIOCETHTOOL */
716 get
= TRUE
; set
= FALSE
;
721 size
= sizeof(int) * 2;
722 get
= TRUE
; set
= TRUE
;
727 size
= sizeof(int) * 2;
728 get
= FALSE
; set
= TRUE
;
731 data
->phy_id
= et
->etc
->phyaddr
;
733 data
->val_out
= (*et
->etc
->chops
->phyrd
)(et
->etc
->ch
, data
->phy_id
, data
->reg_num
);
736 (*et
->etc
->chops
->phywr
)(et
->etc
->ch
, data
->phy_id
, data
->reg_num
, data
->val_in
);
740 get
= FALSE
; set
= TRUE
;
744 if ((buf
= MALLOC(et
->osh
, size
)) == NULL
) {
745 ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", MALLOCED(et
->osh
)));
749 if (set
&& copy_from_user(buf
, ifr
->ifr_data
, size
)) {
750 MFREE(et
->osh
, buf
, size
);
757 error
= et_ethtool(et
, (struct ethtool_cmd
*)buf
);
759 #endif /* SIOCETHTOOL */
762 error
= etc_ioctl(et
->etc
, cmd
- SIOCSETCUP
, buf
) ? -EINVAL
: 0;
768 error
= copy_to_user(ifr
->ifr_data
, buf
, size
);
770 MFREE(et
->osh
, buf
, size
);
775 static struct net_device_stats
*
776 et_get_stats(struct net_device
*dev
)
780 struct net_device_stats
*stats
;
784 ET_TRACE(("et%d: et_get_stats\n", et
->etc
->unit
));
790 bzero(stats
, sizeof(struct net_device_stats
));
794 (*etc
->chops
->statsupd
)(etc
->ch
);
797 stats
->rx_packets
= etc
->rxframe
;
798 stats
->tx_packets
= etc
->txframe
;
799 stats
->rx_bytes
= etc
->rxbyte
;
800 stats
->tx_bytes
= etc
->txbyte
;
801 stats
->rx_errors
= etc
->rxerror
;
802 stats
->tx_errors
= etc
->txerror
;
803 stats
->collisions
= etc
->mib
.tx_total_cols
;
805 stats
->rx_length_errors
= (etc
->mib
.rx_oversize_pkts
+ etc
->mib
.rx_undersize
);
806 stats
->rx_over_errors
= etc
->rxoflo
;
807 stats
->rx_crc_errors
= etc
->mib
.rx_crc_errs
;
808 stats
->rx_frame_errors
= etc
->mib
.rx_align_errs
;
809 stats
->rx_fifo_errors
= etc
->rxoflo
;
810 stats
->rx_missed_errors
= etc
->mib
.rx_missed_pkts
;
812 stats
->tx_fifo_errors
= etc
->txuflo
;
820 et_set_mac_address(struct net_device
*dev
, void *addr
)
823 struct sockaddr
*sa
= (struct sockaddr
*) addr
;
826 ET_TRACE(("et%d: et_set_mac_address\n", et
->etc
->unit
));
831 bcopy(sa
->sa_data
, dev
->dev_addr
, ETHER_ADDR_LEN
);
832 bcopy(dev
->dev_addr
, &et
->etc
->cur_etheraddr
, ETHER_ADDR_LEN
);
838 et_set_multicast_list(struct net_device
*dev
)
842 struct dev_mc_list
*mclist
;
848 ET_TRACE(("et%d: et_set_multicast_list\n", etc
->unit
));
853 etc
->promisc
= (dev
->flags
& IFF_PROMISC
)? TRUE
: FALSE
;
854 etc
->allmulti
= (dev
->flags
& IFF_ALLMULTI
)? TRUE
: FALSE
;
856 /* copy the list of multicasts into our private table */
857 for (i
= 0, mclist
= dev
->mc_list
; mclist
&& (i
< dev
->mc_count
);
858 i
++, mclist
= mclist
->next
) {
859 if (i
>= MAXMULTILIST
) {
860 etc
->allmulti
= TRUE
;
864 etc
->multicast
[i
] = *((struct ether_addr
*) mclist
->dmi_addr
);
875 et_isr(int irq
, void *dev_id
, struct pt_regs
*ptregs
)
882 et
= (et_info_t
*) dev_id
;
883 chops
= et
->etc
->chops
;
886 /* guard against shared interrupts */
890 /* get interrupt condition bits */
891 events
= (*chops
->getintrevents
)(ch
, TRUE
);
894 if (!(events
& INTR_NEW
))
897 ET_TRACE(("et%d: et_isr: events 0x%x\n", et
->etc
->unit
, events
));
898 ET_LOG("et%d: et_isr: events 0x%x", et
->etc
->unit
, events
);
900 /* disable interrupts */
901 (*chops
->intrsoff
)(ch
);
903 /* save intstatus bits */
904 ASSERT(et
->events
== 0);
908 ASSERT(et
->resched
== FALSE
);
909 tasklet_schedule(&et
->tasklet
);
912 ET_LOG("et%d: et_isr ret", et
->etc
->unit
, 0);
914 return IRQ_RETVAL(events
& INTR_NEW
);
927 et
= (et_info_t
*) data
;
928 chops
= et
->etc
->chops
;
932 ET_TRACE(("et%d: et_dpc: events 0x%x\n", et
->etc
->unit
, et
->events
));
933 ET_LOG("et%d: et_dpc: events 0x%x", et
->etc
->unit
, et
->events
);
940 /* get interrupt condition bits again when dpc was rescheduled */
942 et
->events
= (*chops
->getintrevents
)(ch
, FALSE
);
946 if (et
->events
& INTR_RX
) {
948 while ((p
= (*chops
->rx
)(ch
))) {
949 skb
= PKTTONATIVE(osh
, p
);
951 /* more frames, need to reschedule et_dpc() */
952 if (++processed
>= RXBND
) {
958 /* post more rx bufs */
959 (*chops
->rxfill
)(ch
);
962 if (et
->events
& INTR_TX
)
963 (*chops
->txreclaim
)(ch
, FALSE
);
965 if (et
->events
& INTR_ERROR
)
966 if ((*chops
->errors
)(ch
))
969 /* run the tx queue */
970 if (skb_queue_len(&et
->txq
) > 0)
973 /* clear this before re-enabling interrupts */
976 /* something may bring the driver down */
982 /* there may be frames left, reschedule et_dpc() */
984 tasklet_schedule(&et
->tasklet
);
985 /* re-enable interrupts */
987 (*chops
->intrson
)(ch
);
992 ET_LOG("et%d: et_dpc ret", et
->etc
->unit
, 0);
996 et_sendup(et_info_t
*et
, struct sk_buff
*skb
)
1005 /* packet buffer starts with rxhdr */
1006 rxh
= (bcmenetrxh_t
*) skb
->data
;
1008 /* strip off rxhdr */
1009 skb_pull(skb
, HWRXOFF
);
1011 ET_TRACE(("et%d: et_sendup: %d bytes\n", et
->etc
->unit
, skb
->len
));
1012 ET_LOG("et%d: et_sendup: len %d", et
->etc
->unit
, skb
->len
);
1015 etc
->rxbyte
+= skb
->len
;
1017 /* eh should now be aligned 2-mod-4 */
1018 ASSERT(((uint
)skb
->data
& 3) == 2);
1020 /* strip off crc32 */
1021 skb_trim(skb
, skb
->len
- ETHER_CRC_LEN
);
1023 ET_PRHDR("rx", (struct ether_header
*) skb
->data
, skb
->len
, etc
->unit
);
1024 ET_PRPKT("rxpkt", skb
->data
, skb
->len
, etc
->unit
);
1026 /* check for reported frame errors */
1027 flags
= ltoh16(rxh
->flags
);
1028 if (flags
& (RXF_NO
| RXF_RXER
| RXF_CRC
| RXF_OV
))
1031 /* check for invalid data on the unit 1, workaround hw bug */
1032 if (etc
->chip
== BCM4710_CHIP_ID
&& etc
->unit
== 1)
1034 uint8
*ether_dhost
= ((struct ether_header
*)skb
->data
)->ether_dhost
;
1035 if ( !(flags
& (RXF_MULT
| RXF_BRDCAST
)) != !ETHER_ISMULTI(ether_dhost
) ||
1036 !(flags
& RXF_BRDCAST
) != !ETHER_ISBCAST(ether_dhost
) ||
1037 ((flags
& (RXF_MULT
| RXF_BRDCAST
| RXF_MISS
)) == 0 &&
1038 ether_cmp(ether_dhost
, &etc
->cur_etheraddr
)))
1040 bcm_ether_ntoa((struct ether_addr
*)ether_dhost
, eabuf
);
1041 ET_ERROR(("et%d: rx: bad dest address %s [%c%c%c]\n",
1042 etc
->unit
, eabuf
, (flags
& RXF_MULT
) ? 'M' : ' ',
1043 (flags
& RXF_BRDCAST
) ? 'B' : ' ', (flags
& RXF_MISS
) ? 'P' : ' '));
1044 /* schedule reset */
1045 et
->events
|= INTR_ERROR
;
1050 /* Extract priority from payload and store it out-of-band in skb->priority */
1052 pktsetprio(skb
, TRUE
);
1055 skb
->protocol
= eth_type_trans(skb
, et
->dev
);
1060 ET_LOG("et%d: et_sendup ret", et
->etc
->unit
, 0);
1065 bcm_ether_ntoa((struct ether_addr
*)((struct ether_header
*)skb
->data
)->ether_shost
, eabuf
);
1066 if (flags
& RXF_NO
) {
1067 ET_ERROR(("et%d: rx: crc error (odd nibbles) from %s\n", etc
->unit
, eabuf
));
1069 if (flags
& RXF_RXER
) {
1070 ET_ERROR(("et%d: rx: symbol error from %s\n", etc
->unit
, eabuf
));
1072 if ((flags
& RXF_CRC
) == RXF_CRC
) {
1073 ET_ERROR(("et%d: rx: crc error from %s\n", etc
->unit
, eabuf
));
1075 if (flags
& RXF_OV
) {
1076 ET_ERROR(("et%d: rx: fifo overflow\n", etc
->unit
));
1079 dev_kfree_skb_any(skb
);
1085 et_dump(et_info_t
*et
, struct bcmstrbuf
*b
)
1087 bcm_bprintf(b
, "et%d: %s %s version %s\n", et
->etc
->unit
,
1088 __DATE__
, __TIME__
, EPI_VERSION_STR
);
1094 et_link_up(et_info_t
*et
)
1096 ET_ERROR(("et%d: link up (%d%s)\n",
1097 et
->etc
->unit
, et
->etc
->speed
, (et
->etc
->duplex
? "FD" : "HD")));
1101 et_link_down(et_info_t
*et
)
1103 ET_ERROR(("et%d: link down\n", et
->etc
->unit
));
1107 * 47XX-specific shared mdc/mdio contortion:
1108 * Find the et associated with the same chip as <et>
1109 * and coreunit matching <coreunit>.
1112 et_phyfind(et_info_t
*et
, uint coreunit
)
1117 bus
= et
->pdev
->bus
->number
;
1118 slot
= PCI_SLOT(et
->pdev
->devfn
);
1120 /* walk the list et's */
1121 for (tmp
= et_list
; tmp
; tmp
= tmp
->next
) {
1122 if (et
->etc
== NULL
)
1124 if (tmp
->pdev
== NULL
)
1126 if (tmp
->pdev
->bus
->number
!= bus
)
1128 if (tmp
->etc
->nicmode
)
1129 if (PCI_SLOT(tmp
->pdev
->devfn
) != slot
)
1131 if (tmp
->etc
->coreunit
!= coreunit
)
1138 /* shared phy read entry point */
1140 et_phyrd(et_info_t
*et
, uint phyaddr
, uint reg
)
1145 val
= et
->etc
->chops
->phyrd(et
->etc
->ch
, phyaddr
, reg
);
1151 /* shared phy write entry point */
1153 et_phywr(et_info_t
*et
, uint phyaddr
, uint reg
, uint16 val
)
1156 et
->etc
->chops
->phywr(et
->etc
->ch
, phyaddr
, reg
, val
);