~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.38/natty-proposed

« back to all changes in this revision

Viewing changes to updates/compat-wireless-2.6.36/drivers/net/atlx/atlx.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner, Tim Gardner
  • Date: 2011-06-08 10:44:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110608104409-fnl8carkdo15bwsz
Tags: 2.6.38-10.6
[ Tim Gardner ]

Shorten compat-wireless package name to cw to accomodate
CDROM file name length restrictions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* atlx.c -- common functions for Attansic network drivers
2
 
 *
3
 
 * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
4
 
 * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
5
 
 * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
6
 
 * Copyright(c) 2007 Atheros Corporation. All rights reserved.
7
 
 *
8
 
 * Derived from Intel e1000 driver
9
 
 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
10
 
 *
11
 
 * This program is free software; you can redistribute it and/or modify it
12
 
 * under the terms of the GNU General Public License as published by the Free
13
 
 * Software Foundation; either version 2 of the License, or (at your option)
14
 
 * any later version.
15
 
 *
16
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
 
 * more details.
20
 
 *
21
 
 * You should have received a copy of the GNU General Public License along with
22
 
 * this program; if not, write to the Free Software Foundation, Inc., 59
23
 
 * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24
 
 */
25
 
 
26
 
/* Including this file like a header is a temporary hack, I promise. -- CHS */
27
 
#ifndef ATLX_C
28
 
#define ATLX_C
29
 
 
30
 
#include <linux/device.h>
31
 
#include <linux/errno.h>
32
 
#include <linux/etherdevice.h>
33
 
#include <linux/if.h>
34
 
#include <linux/netdevice.h>
35
 
#include <linux/socket.h>
36
 
#include <linux/sockios.h>
37
 
#include <linux/spinlock.h>
38
 
#include <linux/string.h>
39
 
#include <linux/types.h>
40
 
#include <linux/workqueue.h>
41
 
 
42
 
#include "atlx.h"
43
 
 
44
 
static struct atlx_spi_flash_dev flash_table[] = {
45
 
/*      MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */
46
 
        {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62},
47
 
        {"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60},
48
 
        {"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7},
49
 
};
50
 
 
51
 
static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
52
 
{
53
 
        switch (cmd) {
54
 
        case SIOCGMIIPHY:
55
 
        case SIOCGMIIREG:
56
 
        case SIOCSMIIREG:
57
 
                return atlx_mii_ioctl(netdev, ifr, cmd);
58
 
        default:
59
 
                return -EOPNOTSUPP;
60
 
        }
61
 
}
62
 
 
63
 
/*
64
 
 * atlx_set_mac - Change the Ethernet Address of the NIC
65
 
 * @netdev: network interface device structure
66
 
 * @p: pointer to an address structure
67
 
 *
68
 
 * Returns 0 on success, negative on failure
69
 
 */
70
 
static int atlx_set_mac(struct net_device *netdev, void *p)
71
 
{
72
 
        struct atlx_adapter *adapter = netdev_priv(netdev);
73
 
        struct sockaddr *addr = p;
74
 
 
75
 
        if (netif_running(netdev))
76
 
                return -EBUSY;
77
 
 
78
 
        if (!is_valid_ether_addr(addr->sa_data))
79
 
                return -EADDRNOTAVAIL;
80
 
 
81
 
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
82
 
        memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
83
 
 
84
 
        atlx_set_mac_addr(&adapter->hw);
85
 
        return 0;
86
 
}
87
 
 
88
 
static void atlx_check_for_link(struct atlx_adapter *adapter)
89
 
{
90
 
        struct net_device *netdev = adapter->netdev;
91
 
        u16 phy_data = 0;
92
 
 
93
 
        spin_lock(&adapter->lock);
94
 
        adapter->phy_timer_pending = false;
95
 
        atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
96
 
        atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
97
 
        spin_unlock(&adapter->lock);
98
 
 
99
 
        /* notify upper layer link down ASAP */
100
 
        if (!(phy_data & BMSR_LSTATUS)) {
101
 
                /* Link Down */
102
 
                if (netif_carrier_ok(netdev)) {
103
 
                        /* old link state: Up */
104
 
                        dev_info(&adapter->pdev->dev, "%s link is down\n",
105
 
                                netdev->name);
106
 
                        adapter->link_speed = SPEED_0;
107
 
                        netif_carrier_off(netdev);
108
 
                }
109
 
        }
110
 
        schedule_work(&adapter->link_chg_task);
111
 
}
112
 
 
113
 
/*
114
 
 * atlx_set_multi - Multicast and Promiscuous mode set
115
 
 * @netdev: network interface device structure
116
 
 *
117
 
 * The set_multi entry point is called whenever the multicast address
118
 
 * list or the network interface flags are updated.  This routine is
119
 
 * responsible for configuring the hardware for proper multicast,
120
 
 * promiscuous mode, and all-multi behavior.
121
 
 */
122
 
static void atlx_set_multi(struct net_device *netdev)
123
 
{
124
 
        struct atlx_adapter *adapter = netdev_priv(netdev);
125
 
        struct atlx_hw *hw = &adapter->hw;
126
 
        struct netdev_hw_addr *ha;
127
 
        u32 rctl;
128
 
        u32 hash_value;
129
 
 
130
 
        /* Check for Promiscuous and All Multicast modes */
131
 
        rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
132
 
        if (netdev->flags & IFF_PROMISC)
133
 
                rctl |= MAC_CTRL_PROMIS_EN;
134
 
        else if (netdev->flags & IFF_ALLMULTI) {
135
 
                rctl |= MAC_CTRL_MC_ALL_EN;
136
 
                rctl &= ~MAC_CTRL_PROMIS_EN;
137
 
        } else
138
 
                rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
139
 
 
140
 
        iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
141
 
 
142
 
        /* clear the old settings from the multicast hash table */
143
 
        iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
144
 
        iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
145
 
 
146
 
        /* compute mc addresses' hash value ,and put it into hash table */
147
 
        netdev_for_each_mc_addr(ha, netdev) {
148
 
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
149
 
                hash_value = atlx_hash_mc_addr(hw, ha->addr);
150
 
#else
151
 
                hash_value = atlx_hash_mc_addr(hw, ha->dmi_addr);
152
 
#endif
153
 
                atlx_hash_set(hw, hash_value);
154
 
        }
155
 
}
156
 
 
157
 
/*
158
 
 * atlx_irq_enable - Enable default interrupt generation settings
159
 
 * @adapter: board private structure
160
 
 */
161
 
static void atlx_irq_enable(struct atlx_adapter *adapter)
162
 
{
163
 
        iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
164
 
        ioread32(adapter->hw.hw_addr + REG_IMR);
165
 
}
166
 
 
167
 
/*
168
 
 * atlx_irq_disable - Mask off interrupt generation on the NIC
169
 
 * @adapter: board private structure
170
 
 */
171
 
static void atlx_irq_disable(struct atlx_adapter *adapter)
172
 
{
173
 
        iowrite32(0, adapter->hw.hw_addr + REG_IMR);
174
 
        ioread32(adapter->hw.hw_addr + REG_IMR);
175
 
        synchronize_irq(adapter->pdev->irq);
176
 
}
177
 
 
178
 
static void atlx_clear_phy_int(struct atlx_adapter *adapter)
179
 
{
180
 
        u16 phy_data;
181
 
        unsigned long flags;
182
 
 
183
 
        spin_lock_irqsave(&adapter->lock, flags);
184
 
        atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
185
 
        spin_unlock_irqrestore(&adapter->lock, flags);
186
 
}
187
 
 
188
 
/*
189
 
 * atlx_tx_timeout - Respond to a Tx Hang
190
 
 * @netdev: network interface device structure
191
 
 */
192
 
static void atlx_tx_timeout(struct net_device *netdev)
193
 
{
194
 
        struct atlx_adapter *adapter = netdev_priv(netdev);
195
 
        /* Do the reset outside of interrupt context */
196
 
        schedule_work(&adapter->tx_timeout_task);
197
 
}
198
 
 
199
 
/*
200
 
 * atlx_link_chg_task - deal with link change event Out of interrupt context
201
 
 */
202
 
static void atlx_link_chg_task(struct work_struct *work)
203
 
{
204
 
        struct atlx_adapter *adapter;
205
 
        unsigned long flags;
206
 
 
207
 
        adapter = container_of(work, struct atlx_adapter, link_chg_task);
208
 
 
209
 
        spin_lock_irqsave(&adapter->lock, flags);
210
 
        atlx_check_link(adapter);
211
 
        spin_unlock_irqrestore(&adapter->lock, flags);
212
 
}
213
 
 
214
 
static void atlx_vlan_rx_register(struct net_device *netdev,
215
 
        struct vlan_group *grp)
216
 
{
217
 
        struct atlx_adapter *adapter = netdev_priv(netdev);
218
 
        unsigned long flags;
219
 
        u32 ctrl;
220
 
 
221
 
        spin_lock_irqsave(&adapter->lock, flags);
222
 
        /* atlx_irq_disable(adapter); FIXME: confirm/remove */
223
 
        adapter->vlgrp = grp;
224
 
 
225
 
        if (grp) {
226
 
                /* enable VLAN tag insert/strip */
227
 
                ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
228
 
                ctrl |= MAC_CTRL_RMV_VLAN;
229
 
                iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
230
 
        } else {
231
 
                /* disable VLAN tag insert/strip */
232
 
                ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
233
 
                ctrl &= ~MAC_CTRL_RMV_VLAN;
234
 
                iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
235
 
        }
236
 
 
237
 
        /* atlx_irq_enable(adapter); FIXME */
238
 
        spin_unlock_irqrestore(&adapter->lock, flags);
239
 
}
240
 
 
241
 
static void atlx_restore_vlan(struct atlx_adapter *adapter)
242
 
{
243
 
        atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
244
 
}
245
 
 
246
 
#endif /* ATLX_C */