Commit | Line | Data |
---|---|---|
cfb739b4 GKH |
1 | /* |
2 | * Agere Systems Inc. | |
3 | * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs | |
4 | * | |
64f93036 | 5 | * Copyright © 2005 Agere Systems Inc. |
cfb739b4 GKH |
6 | * All rights reserved. |
7 | * http://www.agere.com | |
8 | * | |
9 | *------------------------------------------------------------------------------ | |
10 | * | |
11 | * et131x_initpci.c - Routines and data used to register the driver with the | |
12 | * PCI (and PCI Express) subsystem, as well as basic driver | |
13 | * init and startup. | |
14 | * | |
15 | *------------------------------------------------------------------------------ | |
16 | * | |
17 | * SOFTWARE LICENSE | |
18 | * | |
19 | * This software is provided subject to the following terms and conditions, | |
20 | * which you should read carefully before using the software. Using this | |
21 | * software indicates your acceptance of these terms and conditions. If you do | |
22 | * not agree with these terms and conditions, do not use the software. | |
23 | * | |
64f93036 | 24 | * Copyright © 2005 Agere Systems Inc. |
cfb739b4 GKH |
25 | * All rights reserved. |
26 | * | |
27 | * Redistribution and use in source or binary forms, with or without | |
28 | * modifications, are permitted provided that the following conditions are met: | |
29 | * | |
30 | * . Redistributions of source code must retain the above copyright notice, this | |
31 | * list of conditions and the following Disclaimer as comments in the code as | |
32 | * well as in the documentation and/or other materials provided with the | |
33 | * distribution. | |
34 | * | |
35 | * . Redistributions in binary form must reproduce the above copyright notice, | |
36 | * this list of conditions and the following Disclaimer in the documentation | |
37 | * and/or other materials provided with the distribution. | |
38 | * | |
39 | * . Neither the name of Agere Systems Inc. nor the names of the contributors | |
40 | * may be used to endorse or promote products derived from this software | |
41 | * without specific prior written permission. | |
42 | * | |
43 | * Disclaimer | |
44 | * | |
64f93036 | 45 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
cfb739b4 GKH |
46 | * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF |
47 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY | |
48 | * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN | |
49 | * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY | |
50 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
51 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
52 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
53 | * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT | |
54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
55 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
56 | * DAMAGE. | |
57 | * | |
58 | */ | |
59 | ||
60 | #include "et131x_version.h" | |
cfb739b4 GKH |
61 | #include "et131x_defs.h" |
62 | ||
63 | #include <linux/pci.h> | |
64 | #include <linux/init.h> | |
65 | #include <linux/module.h> | |
66 | #include <linux/types.h> | |
67 | #include <linux/kernel.h> | |
68 | ||
69 | #include <linux/sched.h> | |
70 | #include <linux/ptrace.h> | |
71 | #include <linux/slab.h> | |
72 | #include <linux/ctype.h> | |
73 | #include <linux/string.h> | |
74 | #include <linux/timer.h> | |
75 | #include <linux/interrupt.h> | |
76 | #include <linux/in.h> | |
77 | #include <linux/delay.h> | |
64f93036 AC |
78 | #include <linux/io.h> |
79 | #include <linux/bitops.h> | |
cfb739b4 | 80 | #include <asm/system.h> |
cfb739b4 GKH |
81 | |
82 | #include <linux/netdevice.h> | |
83 | #include <linux/etherdevice.h> | |
84 | #include <linux/skbuff.h> | |
85 | #include <linux/if_arp.h> | |
86 | #include <linux/ioport.h> | |
87 | #include <linux/random.h> | |
88 | ||
89 | #include "et1310_phy.h" | |
90 | #include "et1310_pm.h" | |
91 | #include "et1310_jagcore.h" | |
92 | ||
93 | #include "et131x_adapter.h" | |
94 | #include "et131x_netdev.h" | |
95 | #include "et131x_config.h" | |
96 | #include "et131x_isr.h" | |
97 | ||
98 | #include "et1310_address_map.h" | |
cfb739b4 GKH |
99 | #include "et1310_tx.h" |
100 | #include "et1310_rx.h" | |
101 | #include "et1310_mac.h" | |
102 | #include "et1310_eeprom.h" | |
103 | ||
104 | ||
8c5f20f3 AC |
105 | /* Defines for Parameter Default/Min/Max vaules */ |
106 | #define PARM_SPEED_DUPLEX_MIN 0 | |
107 | #define PARM_SPEED_DUPLEX_MAX 5 | |
108 | ||
109 | /* Module parameter for disabling NMI | |
110 | * et131x_nmi_disable : | |
111 | * Disable NMI (0-2) [0] | |
112 | * 0 : | |
113 | * 1 : | |
114 | * 2 : | |
115 | */ | |
116 | static u32 et131x_nmi_disable; /* 0-2 */ | |
117 | module_param(et131x_nmi_disable, uint, 0); | |
118 | MODULE_PARM_DESC(et131x_nmi_disable, "Disable NMI (0-2) [0]"); | |
119 | ||
120 | /* Module parameter for manual speed setting | |
121 | * Set Link speed and dublex manually (0-5) [0] | |
122 | * 1 : 10Mb Half-Duplex | |
123 | * 2 : 10Mb Full-Duplex | |
124 | * 3 : 100Mb Half-Duplex | |
125 | * 4 : 100Mb Full-Duplex | |
126 | * 5 : 1000Mb Full-Duplex | |
127 | * 0 : Auto Speed Auto Duplex // default | |
128 | */ | |
129 | static u32 et131x_speed_set; | |
130 | module_param(et131x_speed_set, uint, 0); | |
131 | MODULE_PARM_DESC(et131x_speed_set, | |
132 | "Set Link speed and dublex manually (0-5) [0] \n 1 : 10Mb Half-Duplex \n 2 : 10Mb Full-Duplex \n 3 : 100Mb Half-Duplex \n 4 : 100Mb Full-Duplex \n 5 : 1000Mb Full-Duplex \n 0 : Auto Speed Auto Dublex"); | |
133 | ||
cfb739b4 GKH |
134 | /** |
135 | * et131x_find_adapter - Find the adapter and get all the assigned resources | |
136 | * @adapter: pointer to our private adapter structure | |
137 | * | |
138 | * Returns 0 on success, errno on failure (as defined in errno.h) | |
139 | */ | |
140 | int et131x_find_adapter(struct et131x_adapter *adapter, struct pci_dev *pdev) | |
141 | { | |
142 | int result; | |
143 | uint8_t eepromStat; | |
144 | uint8_t maxPayload = 0; | |
145 | uint8_t read_size_reg; | |
5ec3487a | 146 | u8 rev; |
cfb739b4 | 147 | |
cfb739b4 GKH |
148 | /* Allow disabling of Non-Maskable Interrupts in I/O space, to |
149 | * support validation. | |
150 | */ | |
151 | if (adapter->RegistryNMIDisable) { | |
152 | uint8_t RegisterVal; | |
153 | ||
154 | RegisterVal = inb(ET1310_NMI_DISABLE); | |
155 | RegisterVal &= 0xf3; | |
156 | ||
64f93036 | 157 | if (adapter->RegistryNMIDisable == 2) |
cfb739b4 | 158 | RegisterVal |= 0xc; |
cfb739b4 GKH |
159 | |
160 | outb(ET1310_NMI_DISABLE, RegisterVal); | |
161 | } | |
162 | ||
163 | /* We first need to check the EEPROM Status code located at offset | |
164 | * 0xB2 of config space | |
165 | */ | |
166 | result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, | |
167 | &eepromStat); | |
168 | ||
169 | /* THIS IS A WORKAROUND: | |
64f93036 | 170 | * I need to call this function twice to get my card in a |
cfb739b4 GKH |
171 | * LG M1 Express Dual running. I tried also a msleep before this |
172 | * function, because I thougth there could be some time condidions | |
173 | * but it didn't work. Call the whole function twice also work. | |
174 | */ | |
175 | result = pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, | |
176 | &eepromStat); | |
177 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 | 178 | dev_err(&pdev->dev, "Could not read PCI config space for " |
cfb739b4 | 179 | "EEPROM Status\n"); |
cfb739b4 GKH |
180 | return -EIO; |
181 | } | |
182 | ||
183 | /* Determine if the error(s) we care about are present. If they are | |
184 | * present, we need to fail. | |
185 | */ | |
186 | if (eepromStat & 0x4C) { | |
5ec3487a | 187 | result = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); |
cfb739b4 | 188 | if (result != PCIBIOS_SUCCESSFUL) { |
15700039 | 189 | dev_err(&pdev->dev, |
cfb739b4 GKH |
190 | "Could not read PCI config space for " |
191 | "Revision ID\n"); | |
cfb739b4 | 192 | return -EIO; |
5ec3487a | 193 | } else if (rev == 0x01) { |
cfb739b4 | 194 | int32_t nLoop; |
9fa81099 | 195 | uint8_t temp[4] = { 0xFE, 0x13, 0x10, 0xFF }; |
cfb739b4 GKH |
196 | |
197 | /* Re-write the first 4 bytes if we have an eeprom | |
198 | * present and the revision id is 1, this fixes the | |
199 | * corruption seen with 1310 B Silicon | |
200 | */ | |
201 | for (nLoop = 0; nLoop < 3; nLoop++) { | |
13071fde | 202 | EepromWriteByte(adapter, nLoop, temp[nLoop]); |
cfb739b4 GKH |
203 | } |
204 | } | |
205 | ||
15700039 | 206 | dev_err(&pdev->dev, "Fatal EEPROM Status Error - 0x%04x\n", eepromStat); |
cfb739b4 GKH |
207 | |
208 | /* This error could mean that there was an error reading the | |
209 | * eeprom or that the eeprom doesn't exist. We will treat | |
210 | * each case the same and not try to gather additional | |
211 | * information that normally would come from the eeprom, like | |
212 | * MAC Address | |
213 | */ | |
9fa81099 | 214 | adapter->has_eeprom = 0; |
cfb739b4 | 215 | return -EIO; |
15700039 | 216 | } else |
9fa81099 | 217 | adapter->has_eeprom = 1; |
cfb739b4 GKH |
218 | |
219 | /* Read the EEPROM for information regarding LED behavior. Refer to | |
220 | * ET1310_phy.c, et131x_xcvr_init(), for its use. | |
221 | */ | |
13071fde AC |
222 | EepromReadByte(adapter, 0x70, &adapter->eepromData[0]); |
223 | EepromReadByte(adapter, 0x71, &adapter->eepromData[1]); | |
cfb739b4 | 224 | |
64f93036 AC |
225 | if (adapter->eepromData[0] != 0xcd) |
226 | /* Disable all optional features */ | |
227 | adapter->eepromData[1] = 0x00; | |
cfb739b4 GKH |
228 | |
229 | /* Let's set up the PORT LOGIC Register. First we need to know what | |
230 | * the max_payload_size is | |
231 | */ | |
232 | result = pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &maxPayload); | |
233 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 AC |
234 | dev_err(&pdev->dev, |
235 | "Could not read PCI config space for Max Payload Size\n"); | |
cfb739b4 GKH |
236 | return -EIO; |
237 | } | |
238 | ||
239 | /* Program the Ack/Nak latency and replay timers */ | |
64f93036 | 240 | maxPayload &= 0x07; /* Only the lower 3 bits are valid */ |
cfb739b4 GKH |
241 | |
242 | if (maxPayload < 2) { | |
243 | const uint16_t AckNak[2] = { 0x76, 0xD0 }; | |
244 | const uint16_t Replay[2] = { 0x1E0, 0x2ED }; | |
245 | ||
246 | result = pci_write_config_word(pdev, ET1310_PCI_ACK_NACK, | |
247 | AckNak[maxPayload]); | |
248 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 AC |
249 | dev_err(&pdev->dev, |
250 | "Could not write PCI config space for ACK/NAK\n"); | |
cfb739b4 GKH |
251 | return -EIO; |
252 | } | |
253 | ||
254 | result = pci_write_config_word(pdev, ET1310_PCI_REPLAY, | |
255 | Replay[maxPayload]); | |
256 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 AC |
257 | dev_err(&pdev->dev, |
258 | "Could not write PCI config space for Replay Timer\n"); | |
cfb739b4 GKH |
259 | return -EIO; |
260 | } | |
261 | } | |
262 | ||
263 | /* l0s and l1 latency timers. We are using default values. | |
264 | * Representing 001 for L0s and 010 for L1 | |
265 | */ | |
266 | result = pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11); | |
267 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 AC |
268 | dev_err(&pdev->dev, |
269 | "Could not write PCI config space for Latency Timers\n"); | |
cfb739b4 GKH |
270 | return -EIO; |
271 | } | |
272 | ||
273 | /* Change the max read size to 2k */ | |
274 | result = pci_read_config_byte(pdev, 0x51, &read_size_reg); | |
275 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 | 276 | dev_err(&pdev->dev, |
64f93036 | 277 | "Could not read PCI config space for Max read size\n"); |
cfb739b4 GKH |
278 | return -EIO; |
279 | } | |
280 | ||
281 | read_size_reg &= 0x8f; | |
282 | read_size_reg |= 0x40; | |
283 | ||
284 | result = pci_write_config_byte(pdev, 0x51, read_size_reg); | |
285 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 | 286 | dev_err(&pdev->dev, |
64f93036 | 287 | "Could not write PCI config space for Max read size\n"); |
cfb739b4 GKH |
288 | return -EIO; |
289 | } | |
290 | ||
cfb739b4 GKH |
291 | /* Get MAC address from config space if an eeprom exists, otherwise |
292 | * the MAC address there will not be valid | |
293 | */ | |
9fa81099 | 294 | if (adapter->has_eeprom) { |
cfb739b4 GKH |
295 | int i; |
296 | ||
297 | for (i = 0; i < ETH_ALEN; i++) { | |
298 | result = pci_read_config_byte( | |
299 | pdev, ET1310_PCI_MAC_ADDRESS + i, | |
300 | adapter->PermanentAddress + i); | |
301 | if (result != PCIBIOS_SUCCESSFUL) { | |
15700039 | 302 | dev_err(&pdev->dev, ";Could not read PCI config space for MAC address\n"); |
cfb739b4 GKH |
303 | return -EIO; |
304 | } | |
305 | } | |
306 | } | |
cfb739b4 GKH |
307 | return 0; |
308 | } | |
309 | ||
310 | /** | |
311 | * et131x_error_timer_handler | |
312 | * @data: timer-specific variable; here a pointer to our adapter structure | |
313 | * | |
314 | * The routine called when the error timer expires, to track the number of | |
315 | * recurring errors. | |
316 | */ | |
317 | void et131x_error_timer_handler(unsigned long data) | |
318 | { | |
25ad00bb | 319 | struct et131x_adapter *etdev = (struct et131x_adapter *) data; |
f2c98d27 | 320 | u32 pm_csr; |
cfb739b4 | 321 | |
f2c98d27 | 322 | pm_csr = readl(&etdev->regs->global.pm_csr); |
cfb739b4 | 323 | |
f2c98d27 | 324 | if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) |
94831463 AC |
325 | UpdateMacStatHostCounters(etdev); |
326 | else | |
15700039 AC |
327 | dev_err(&etdev->pdev->dev, |
328 | "No interrupts, in PHY coma, pm_csr = 0x%x\n", pm_csr); | |
cfb739b4 | 329 | |
25ad00bb AC |
330 | if (!etdev->Bmsr.bits.link_status && |
331 | etdev->RegistryPhyComa && | |
332 | etdev->PoMgmt.TransPhyComaModeOnBoot < 11) { | |
333 | etdev->PoMgmt.TransPhyComaModeOnBoot++; | |
cfb739b4 GKH |
334 | } |
335 | ||
25ad00bb AC |
336 | if (etdev->PoMgmt.TransPhyComaModeOnBoot == 10) { |
337 | if (!etdev->Bmsr.bits.link_status | |
338 | && etdev->RegistryPhyComa) { | |
f2c98d27 | 339 | if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { |
64f93036 AC |
340 | /* NOTE - This was originally a 'sync with |
341 | * interrupt'. How to do that under Linux? | |
342 | */ | |
25ad00bb AC |
343 | et131x_enable_interrupts(etdev); |
344 | EnablePhyComa(etdev); | |
cfb739b4 GKH |
345 | } |
346 | } | |
347 | } | |
348 | ||
349 | /* This is a periodic timer, so reschedule */ | |
25ad00bb | 350 | mod_timer(&etdev->ErrorTimer, jiffies + |
64f93036 | 351 | TX_ERROR_PERIOD * HZ / 1000); |
cfb739b4 GKH |
352 | } |
353 | ||
354 | /** | |
355 | * et131x_link_detection_handler | |
356 | * | |
357 | * Timer function for link up at driver load time | |
358 | */ | |
359 | void et131x_link_detection_handler(unsigned long data) | |
360 | { | |
25ad00bb | 361 | struct et131x_adapter *etdev = (struct et131x_adapter *) data; |
37628606 | 362 | unsigned long flags; |
cfb739b4 | 363 | |
25ad00bb | 364 | if (etdev->MediaState == 0) { |
37628606 | 365 | spin_lock_irqsave(&etdev->Lock, flags); |
cfb739b4 | 366 | |
25ad00bb | 367 | etdev->MediaState = NETIF_STATUS_MEDIA_DISCONNECT; |
f6b35d66 | 368 | etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION; |
cfb739b4 | 369 | |
37628606 | 370 | spin_unlock_irqrestore(&etdev->Lock, flags); |
cfb739b4 | 371 | |
25ad00bb | 372 | netif_carrier_off(etdev->netdev); |
cfb739b4 GKH |
373 | } |
374 | } | |
375 | ||
b8c4cc46 AC |
376 | /** |
377 | * et131x_configure_global_regs - configure JAGCore global regs | |
378 | * @etdev: pointer to our adapter structure | |
379 | * | |
380 | * Used to configure the global registers on the JAGCore | |
381 | */ | |
382 | void ConfigGlobalRegs(struct et131x_adapter *etdev) | |
383 | { | |
e266b202 | 384 | struct _GLOBAL_t __iomem *regs = &etdev->regs->global; |
b8c4cc46 | 385 | |
b8c4cc46 AC |
386 | if (etdev->RegistryPhyLoopbk == false) { |
387 | if (etdev->RegistryJumboPacket < 2048) { | |
388 | /* Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word | |
389 | * block of RAM that the driver can split between Tx | |
390 | * and Rx as it desires. Our default is to split it | |
391 | * 50/50: | |
392 | */ | |
e266b202 AC |
393 | writel(0, ®s->rxq_start_addr); |
394 | writel(PARM_RX_MEM_END_DEF, ®s->rxq_end_addr); | |
395 | writel(PARM_RX_MEM_END_DEF + 1, ®s->txq_start_addr); | |
396 | writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); | |
b8c4cc46 AC |
397 | } else if (etdev->RegistryJumboPacket < 8192) { |
398 | /* For jumbo packets > 2k but < 8k, split 50-50. */ | |
e266b202 AC |
399 | writel(0, ®s->rxq_start_addr); |
400 | writel(INTERNAL_MEM_RX_OFFSET, ®s->rxq_end_addr); | |
401 | writel(INTERNAL_MEM_RX_OFFSET + 1, ®s->txq_start_addr); | |
402 | writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); | |
b8c4cc46 AC |
403 | } else { |
404 | /* 9216 is the only packet size greater than 8k that | |
405 | * is available. The Tx buffer has to be big enough | |
406 | * for one whole packet on the Tx side. We'll make | |
407 | * the Tx 9408, and give the rest to Rx | |
408 | */ | |
e266b202 AC |
409 | writel(0x0000, ®s->rxq_start_addr); |
410 | writel(0x01b3, ®s->rxq_end_addr); | |
411 | writel(0x01b4, ®s->txq_start_addr); | |
412 | writel(INTERNAL_MEM_SIZE - 1,®s->txq_end_addr); | |
b8c4cc46 AC |
413 | } |
414 | ||
415 | /* Initialize the loopback register. Disable all loopbacks. */ | |
bc7f9c59 | 416 | writel(0, ®s->loopback); |
b8c4cc46 AC |
417 | } else { |
418 | /* For PHY Line loopback, the memory is configured as if Tx | |
419 | * and Rx both have all the memory. This is because the | |
420 | * RxMAC will write data into the space, and the TxMAC will | |
421 | * read it out. | |
422 | */ | |
e266b202 AC |
423 | writel(0, ®s->rxq_start_addr); |
424 | writel(INTERNAL_MEM_SIZE - 1, ®s->rxq_end_addr); | |
425 | writel(0, ®s->txq_start_addr); | |
426 | writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); | |
b8c4cc46 AC |
427 | |
428 | /* Initialize the loopback register (MAC loopback). */ | |
bc7f9c59 | 429 | writel(ET_LOOP_MAC, ®s->loopback); |
b8c4cc46 AC |
430 | } |
431 | ||
432 | /* MSI Register */ | |
e266b202 | 433 | writel(0, ®s->msi_config); |
b8c4cc46 AC |
434 | |
435 | /* By default, disable the watchdog timer. It will be enabled when | |
436 | * a packet is queued. | |
437 | */ | |
e266b202 | 438 | writel(0, ®s->watchdog_timer); |
b8c4cc46 AC |
439 | } |
440 | ||
441 | ||
cfb739b4 GKH |
442 | /** |
443 | * et131x_adapter_setup - Set the adapter up as per cassini+ documentation | |
444 | * @adapter: pointer to our private adapter structure | |
445 | * | |
446 | * Returns 0 on success, errno on failure (as defined in errno.h) | |
447 | */ | |
25ad00bb | 448 | int et131x_adapter_setup(struct et131x_adapter *etdev) |
cfb739b4 GKH |
449 | { |
450 | int status = 0; | |
451 | ||
cfb739b4 | 452 | /* Configure the JAGCore */ |
25ad00bb | 453 | ConfigGlobalRegs(etdev); |
cfb739b4 | 454 | |
25ad00bb | 455 | ConfigMACRegs1(etdev); |
b8c4cc46 AC |
456 | |
457 | /* Configure the MMC registers */ | |
458 | /* All we need to do is initialize the Memory Control Register */ | |
459 | writel(ET_MMC_ENABLE, &etdev->regs->mmc.mmc_ctrl); | |
cfb739b4 | 460 | |
25ad00bb AC |
461 | ConfigRxMacRegs(etdev); |
462 | ConfigTxMacRegs(etdev); | |
cfb739b4 | 463 | |
25ad00bb AC |
464 | ConfigRxDmaRegs(etdev); |
465 | ConfigTxDmaRegs(etdev); | |
cfb739b4 | 466 | |
25ad00bb | 467 | ConfigMacStatRegs(etdev); |
cfb739b4 GKH |
468 | |
469 | /* Move the following code to Timer function?? */ | |
25ad00bb | 470 | status = et131x_xcvr_find(etdev); |
cfb739b4 | 471 | |
64f93036 | 472 | if (status != 0) |
15700039 | 473 | dev_warn(&etdev->pdev->dev, "Could not find the xcvr\n"); |
cfb739b4 GKH |
474 | |
475 | /* Prepare the TRUEPHY library. */ | |
25ad00bb | 476 | ET1310_PhyInit(etdev); |
cfb739b4 GKH |
477 | |
478 | /* Reset the phy now so changes take place */ | |
25ad00bb | 479 | ET1310_PhyReset(etdev); |
cfb739b4 GKH |
480 | |
481 | /* Power down PHY */ | |
25ad00bb | 482 | ET1310_PhyPowerDown(etdev, 1); |
cfb739b4 GKH |
483 | |
484 | /* | |
485 | * We need to turn off 1000 base half dulplex, the mac does not | |
486 | * support it. For the 10/100 part, turn off all gig advertisement | |
487 | */ | |
5ec3487a | 488 | if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST) |
25ad00bb | 489 | ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); |
64f93036 | 490 | else |
25ad00bb | 491 | ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); |
cfb739b4 GKH |
492 | |
493 | /* Power up PHY */ | |
25ad00bb | 494 | ET1310_PhyPowerDown(etdev, 0); |
cfb739b4 | 495 | |
25ad00bb | 496 | et131x_setphy_normal(etdev); |
15700039 | 497 | ; return status; |
cfb739b4 GKH |
498 | } |
499 | ||
500 | /** | |
501 | * et131x_setup_hardware_properties - set up the MAC Address on the ET1310 | |
502 | * @adapter: pointer to our private adapter structure | |
503 | */ | |
504 | void et131x_setup_hardware_properties(struct et131x_adapter *adapter) | |
505 | { | |
cfb739b4 GKH |
506 | /* If have our default mac from registry and no mac address from |
507 | * EEPROM then we need to generate the last octet and set it on the | |
508 | * device | |
509 | */ | |
9fa81099 AC |
510 | if (adapter->PermanentAddress[0] == 0x00 && |
511 | adapter->PermanentAddress[1] == 0x00 && | |
512 | adapter->PermanentAddress[2] == 0x00 && | |
513 | adapter->PermanentAddress[3] == 0x00 && | |
514 | adapter->PermanentAddress[4] == 0x00 && | |
515 | adapter->PermanentAddress[5] == 0x00) { | |
516 | /* | |
517 | * We need to randomly generate the last octet so we | |
518 | * decrease our chances of setting the mac address to | |
519 | * same as another one of our cards in the system | |
520 | */ | |
521 | get_random_bytes(&adapter->CurrentAddress[5], 1); | |
522 | /* | |
523 | * We have the default value in the register we are | |
524 | * working with so we need to copy the current | |
525 | * address into the permanent address | |
526 | */ | |
527 | memcpy(adapter->PermanentAddress, | |
528 | adapter->CurrentAddress, ETH_ALEN); | |
529 | } else { | |
530 | /* We do not have an override address, so set the | |
531 | * current address to the permanent address and add | |
532 | * it to the device | |
533 | */ | |
534 | memcpy(adapter->CurrentAddress, | |
535 | adapter->PermanentAddress, ETH_ALEN); | |
cfb739b4 | 536 | } |
cfb739b4 GKH |
537 | } |
538 | ||
539 | /** | |
540 | * et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310 | |
541 | * @adapter: pointer to our private adapter structure | |
542 | */ | |
543 | void et131x_soft_reset(struct et131x_adapter *adapter) | |
544 | { | |
cfb739b4 | 545 | /* Disable MAC Core */ |
f3f415a3 | 546 | writel(0xc00f0000, &adapter->regs->mac.cfg1.value); |
cfb739b4 GKH |
547 | |
548 | /* Set everything to a reset value */ | |
b8c4cc46 | 549 | writel(0x7F, &adapter->regs->global.sw_reset); |
f3f415a3 AC |
550 | writel(0x000f0000, &adapter->regs->mac.cfg1.value); |
551 | writel(0x00000000, &adapter->regs->mac.cfg1.value); | |
cfb739b4 GKH |
552 | } |
553 | ||
554 | /** | |
555 | * et131x_align_allocated_memory - Align allocated memory on a given boundary | |
556 | * @adapter: pointer to our adapter structure | |
557 | * @phys_addr: pointer to Physical address | |
558 | * @offset: pointer to the offset variable | |
559 | * @mask: correct mask | |
560 | */ | |
561 | void et131x_align_allocated_memory(struct et131x_adapter *adapter, | |
562 | uint64_t *phys_addr, | |
563 | uint64_t *offset, uint64_t mask) | |
564 | { | |
565 | uint64_t new_addr; | |
566 | ||
cfb739b4 GKH |
567 | *offset = 0; |
568 | ||
569 | new_addr = *phys_addr & ~mask; | |
570 | ||
571 | if (new_addr != *phys_addr) { | |
572 | /* Move to next aligned block */ | |
573 | new_addr += mask + 1; | |
574 | /* Return offset for adjusting virt addr */ | |
575 | *offset = new_addr - *phys_addr; | |
576 | /* Return new physical address */ | |
577 | *phys_addr = new_addr; | |
578 | } | |
cfb739b4 GKH |
579 | } |
580 | ||
581 | /** | |
582 | * et131x_adapter_memory_alloc | |
583 | * @adapter: pointer to our private adapter structure | |
584 | * | |
585 | * Returns 0 on success, errno on failure (as defined in errno.h). | |
586 | * | |
587 | * Allocate all the memory blocks for send, receive and others. | |
588 | */ | |
589 | int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) | |
590 | { | |
591 | int status = 0; | |
592 | ||
cfb739b4 GKH |
593 | do { |
594 | /* Allocate memory for the Tx Ring */ | |
595 | status = et131x_tx_dma_memory_alloc(adapter); | |
596 | if (status != 0) { | |
15700039 | 597 | dev_err(&adapter->pdev->dev, |
cfb739b4 GKH |
598 | "et131x_tx_dma_memory_alloc FAILED\n"); |
599 | break; | |
600 | } | |
601 | ||
602 | /* Receive buffer memory allocation */ | |
603 | status = et131x_rx_dma_memory_alloc(adapter); | |
604 | if (status != 0) { | |
15700039 | 605 | dev_err(&adapter->pdev->dev, |
cfb739b4 GKH |
606 | "et131x_rx_dma_memory_alloc FAILED\n"); |
607 | et131x_tx_dma_memory_free(adapter); | |
608 | break; | |
609 | } | |
610 | ||
611 | /* Init receive data structures */ | |
612 | status = et131x_init_recv(adapter); | |
613 | if (status != 0) { | |
15700039 AC |
614 | dev_err(&adapter->pdev->dev, |
615 | "et131x_init_recv FAILED\n"); | |
cfb739b4 GKH |
616 | et131x_tx_dma_memory_free(adapter); |
617 | et131x_rx_dma_memory_free(adapter); | |
618 | break; | |
619 | } | |
620 | } while (0); | |
cfb739b4 GKH |
621 | return status; |
622 | } | |
623 | ||
624 | /** | |
625 | * et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx | |
626 | * @adapter: pointer to our private adapter structure | |
627 | */ | |
628 | void et131x_adapter_memory_free(struct et131x_adapter *adapter) | |
629 | { | |
cfb739b4 GKH |
630 | /* Free DMA memory */ |
631 | et131x_tx_dma_memory_free(adapter); | |
632 | et131x_rx_dma_memory_free(adapter); | |
cfb739b4 GKH |
633 | } |
634 | ||
8c5f20f3 AC |
635 | /** |
636 | * et131x_config_parse | |
637 | * @etdev: pointer to the private adapter struct | |
638 | * | |
639 | * Parses a configuration from some location (module parameters, for example) | |
640 | * into the private adapter struct. This really has no sensible analogy in | |
641 | * Linux as sysfs parameters are dynamic. Several things that were hee could | |
642 | * go into sysfs, but other stuff like speed handling is part of the mii | |
643 | * interfaces/ethtool. | |
644 | */ | |
645 | void et131x_config_parse(struct et131x_adapter *etdev) | |
646 | { | |
647 | static const u8 default_mac[] = { 0x00, 0x05, 0x3d, 0x00, 0x02, 0x00 }; | |
648 | static const u8 duplex[] = { 0, 1, 2, 1, 2, 2 }; | |
649 | static const u16 speed[] = { 0, 10, 10, 100, 100, 1000 }; | |
650 | ||
8c5f20f3 | 651 | if (et131x_speed_set) |
15700039 AC |
652 | dev_info(&etdev->pdev->dev, |
653 | "Speed set manually to : %d \n", et131x_speed_set); | |
8c5f20f3 AC |
654 | |
655 | etdev->SpeedDuplex = et131x_speed_set; | |
656 | etdev->RegistryJumboPacket = 1514; /* 1514-9216 */ | |
657 | ||
658 | etdev->RegistryNMIDisable = et131x_nmi_disable; | |
659 | ||
660 | /* Set the MAC address to a default */ | |
661 | memcpy(etdev->CurrentAddress, default_mac, ETH_ALEN); | |
662 | ||
663 | /* Decode SpeedDuplex | |
664 | * | |
665 | * Set up as if we are auto negotiating always and then change if we | |
666 | * go into force mode | |
667 | * | |
668 | * If we are the 10/100 device, and gigabit is somehow requested then | |
669 | * knock it down to 100 full. | |
670 | */ | |
671 | if (etdev->pdev->device == ET131X_PCI_DEVICE_ID_FAST && | |
672 | etdev->SpeedDuplex == 5) | |
673 | etdev->SpeedDuplex = 4; | |
674 | ||
675 | etdev->AiForceSpeed = speed[etdev->SpeedDuplex]; | |
676 | etdev->AiForceDpx = duplex[etdev->SpeedDuplex]; /* Auto FDX */ | |
8c5f20f3 AC |
677 | } |
678 | ||
679 | ||
7ca5d422 AC |
680 | /** |
681 | * et131x_pci_remove | |
682 | * @pdev: a pointer to the device's pci_dev structure | |
683 | * | |
684 | * Registered in the pci_driver structure, this function is called when the | |
685 | * PCI subsystem detects that a PCI device which matches the information | |
686 | * contained in the pci_device_id table has been removed. | |
687 | */ | |
688 | ||
689 | void __devexit et131x_pci_remove(struct pci_dev *pdev) | |
690 | { | |
691 | struct net_device *netdev; | |
692 | struct et131x_adapter *adapter; | |
693 | ||
694 | /* Retrieve the net_device pointer from the pci_dev struct, as well | |
695 | * as the private adapter struct | |
696 | */ | |
697 | netdev = (struct net_device *) pci_get_drvdata(pdev); | |
698 | adapter = netdev_priv(netdev); | |
699 | ||
700 | /* Perform device cleanup */ | |
701 | unregister_netdev(netdev); | |
702 | et131x_adapter_memory_free(adapter); | |
703 | iounmap(adapter->regs); | |
704 | pci_dev_put(adapter->pdev); | |
705 | free_netdev(netdev); | |
706 | pci_release_regions(pdev); | |
707 | pci_disable_device(pdev); | |
708 | } | |
709 | ||
710 | ||
cfb739b4 GKH |
711 | /** |
712 | * et131x_pci_setup - Perform device initialization | |
713 | * @pdev: a pointer to the device's pci_dev structure | |
714 | * @ent: this device's entry in the pci_device_id table | |
715 | * | |
716 | * Returns 0 on success, errno on failure (as defined in errno.h) | |
717 | * | |
718 | * Registered in the pci_driver structure, this function is called when the | |
719 | * PCI subsystem finds a new PCI device which matches the information | |
720 | * contained in the pci_device_id table. This routine is the equivalent to | |
721 | * a device insertion routine. | |
722 | */ | |
7ca5d422 | 723 | |
cfb739b4 GKH |
724 | int __devinit et131x_pci_setup(struct pci_dev *pdev, |
725 | const struct pci_device_id *ent) | |
726 | { | |
727 | int result = 0; | |
728 | int pm_cap; | |
729 | bool pci_using_dac; | |
730 | struct net_device *netdev = NULL; | |
731 | struct et131x_adapter *adapter = NULL; | |
732 | ||
cfb739b4 GKH |
733 | /* Enable the device via the PCI subsystem */ |
734 | result = pci_enable_device(pdev); | |
735 | if (result != 0) { | |
15700039 AC |
736 | dev_err(&adapter->pdev->dev, |
737 | "pci_enable_device() failed\n"); | |
cfb739b4 GKH |
738 | goto out; |
739 | } | |
740 | ||
741 | /* Perform some basic PCI checks */ | |
742 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { | |
15700039 | 743 | dev_err(&adapter->pdev->dev, |
cfb739b4 GKH |
744 | "Can't find PCI device's base address\n"); |
745 | result = -ENODEV; | |
746 | goto out; | |
747 | } | |
748 | ||
749 | result = pci_request_regions(pdev, DRIVER_NAME); | |
750 | if (result != 0) { | |
15700039 AC |
751 | dev_err(&adapter->pdev->dev, |
752 | "Can't get PCI resources\n"); | |
cfb739b4 GKH |
753 | goto err_disable; |
754 | } | |
755 | ||
756 | /* Enable PCI bus mastering */ | |
cfb739b4 GKH |
757 | pci_set_master(pdev); |
758 | ||
759 | /* Query PCI for Power Mgmt Capabilities | |
760 | * | |
761 | * NOTE: Now reading PowerMgmt in another location; is this still | |
762 | * needed? | |
763 | */ | |
764 | pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | |
765 | if (pm_cap == 0) { | |
15700039 | 766 | dev_err(&adapter->pdev->dev, |
cfb739b4 GKH |
767 | "Cannot find Power Management capabilities\n"); |
768 | result = -EIO; | |
769 | goto err_release_res; | |
770 | } | |
771 | ||
772 | /* Check the DMA addressing support of this device */ | |
773 | if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { | |
cfb739b4 GKH |
774 | pci_using_dac = true; |
775 | ||
776 | result = | |
777 | pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); | |
778 | if (result != 0) { | |
15700039 | 779 | dev_err(&pdev->dev, |
cfb739b4 GKH |
780 | "Unable to obtain 64 bit DMA for consistent allocations\n"); |
781 | goto err_release_res; | |
782 | } | |
783 | } else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) { | |
cfb739b4 GKH |
784 | pci_using_dac = false; |
785 | } else { | |
15700039 AC |
786 | dev_err(&adapter->pdev->dev, |
787 | "No usable DMA addressing method\n"); | |
cfb739b4 GKH |
788 | result = -EIO; |
789 | goto err_release_res; | |
790 | } | |
791 | ||
792 | /* Allocate netdev and private adapter structs */ | |
cfb739b4 GKH |
793 | netdev = et131x_device_alloc(); |
794 | if (netdev == NULL) { | |
15700039 AC |
795 | dev_err(&adapter->pdev->dev, |
796 | "Couldn't alloc netdev struct\n"); | |
cfb739b4 GKH |
797 | result = -ENOMEM; |
798 | goto err_release_res; | |
799 | } | |
800 | ||
801 | /* Setup the fundamental net_device and private adapter structure elements */ | |
cfb739b4 | 802 | SET_NETDEV_DEV(netdev, &pdev->dev); |
64f93036 | 803 | /* |
cfb739b4 | 804 | if (pci_using_dac) { |
64f93036 | 805 | netdev->features |= NETIF_F_HIGHDMA; |
cfb739b4 | 806 | } |
64f93036 | 807 | */ |
cfb739b4 GKH |
808 | |
809 | /* | |
810 | * NOTE - Turn this on when we're ready to deal with SG-DMA | |
811 | * | |
812 | * NOTE: According to "Linux Device Drivers", 3rd ed, Rubini et al, | |
813 | * if checksumming is not performed in HW, then the kernel will not | |
814 | * use SG. | |
815 | * From pp 510-511: | |
816 | * | |
817 | * "Note that the kernel does not perform scatter/gather I/O to your | |
818 | * device if it does not also provide some form of checksumming as | |
819 | * well. The reason is that, if the kernel has to make a pass over a | |
820 | * fragmented ("nonlinear") packet to calculate the checksum, it | |
821 | * might as well copy the data and coalesce the packet at the same | |
822 | * time." | |
823 | * | |
824 | * This has been verified by setting the flags below and still not | |
825 | * receiving a scattered buffer from the network stack, so leave it | |
826 | * off until checksums are calculated in HW. | |
827 | */ | |
64f93036 AC |
828 | /* netdev->features |= NETIF_F_SG; */ |
829 | /* netdev->features |= NETIF_F_NO_CSUM; */ | |
830 | /* netdev->features |= NETIF_F_LLTX; */ | |
cfb739b4 GKH |
831 | |
832 | /* Allocate private adapter struct and copy in relevant information */ | |
833 | adapter = netdev_priv(netdev); | |
6ae56042 | 834 | adapter->pdev = pci_dev_get(pdev); |
cfb739b4 | 835 | adapter->netdev = netdev; |
cfb739b4 GKH |
836 | |
837 | /* Do the same for the netdev struct */ | |
838 | netdev->irq = pdev->irq; | |
839 | netdev->base_addr = pdev->resource[0].start; | |
840 | ||
841 | /* Initialize spinlocks here */ | |
cfb739b4 GKH |
842 | spin_lock_init(&adapter->Lock); |
843 | spin_lock_init(&adapter->TCBSendQLock); | |
844 | spin_lock_init(&adapter->TCBReadyQLock); | |
845 | spin_lock_init(&adapter->SendHWLock); | |
846 | spin_lock_init(&adapter->SendWaitLock); | |
847 | spin_lock_init(&adapter->RcvLock); | |
848 | spin_lock_init(&adapter->RcvPendLock); | |
849 | spin_lock_init(&adapter->FbrLock); | |
850 | spin_lock_init(&adapter->PHYLock); | |
851 | ||
852 | /* Parse configuration parameters into the private adapter struct */ | |
853 | et131x_config_parse(adapter); | |
854 | ||
855 | /* Find the physical adapter | |
856 | * | |
857 | * NOTE: This is the equivalent of the MpFindAdapter() routine; can we | |
858 | * lump it's init with the device specific init below into a | |
859 | * single init function? | |
860 | */ | |
64f93036 | 861 | /* while (et131x_find_adapter(adapter, pdev) != 0); */ |
cfb739b4 GKH |
862 | et131x_find_adapter(adapter, pdev); |
863 | ||
864 | /* Map the bus-relative registers to system virtual memory */ | |
cfb739b4 | 865 | |
f3f415a3 | 866 | adapter->regs = ioremap_nocache(pci_resource_start(pdev, 0), |
cfb739b4 | 867 | pci_resource_len(pdev, 0)); |
f3f415a3 | 868 | if (adapter->regs == NULL) { |
15700039 | 869 | dev_err(&pdev->dev, "Cannot map device registers\n"); |
cfb739b4 GKH |
870 | result = -ENOMEM; |
871 | goto err_free_dev; | |
872 | } | |
873 | ||
874 | /* Perform device-specific initialization here (See code below) */ | |
875 | ||
876 | /* If Phy COMA mode was enabled when we went down, disable it here. */ | |
f2c98d27 | 877 | writel(ET_PMCSR_INIT, &adapter->regs->global.pm_csr); |
cfb739b4 GKH |
878 | |
879 | /* Issue a global reset to the et1310 */ | |
cfb739b4 GKH |
880 | et131x_soft_reset(adapter); |
881 | ||
882 | /* Disable all interrupts (paranoid) */ | |
cfb739b4 GKH |
883 | et131x_disable_interrupts(adapter); |
884 | ||
885 | /* Allocate DMA memory */ | |
886 | result = et131x_adapter_memory_alloc(adapter); | |
887 | if (result != 0) { | |
15700039 | 888 | dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n"); |
cfb739b4 GKH |
889 | goto err_iounmap; |
890 | } | |
891 | ||
892 | /* Init send data structures */ | |
cfb739b4 GKH |
893 | et131x_init_send(adapter); |
894 | ||
cfb739b4 GKH |
895 | /* Register the interrupt |
896 | * | |
897 | * NOTE - This is being done in the open routine, where most other | |
898 | * Linux drivers setup IRQ handlers. Make sure device | |
899 | * interrupts are not turned on before the IRQ is registered!! | |
900 | * | |
901 | * What we will do here is setup the task structure for the | |
902 | * ISR's deferred handler | |
903 | */ | |
904 | INIT_WORK(&adapter->task, et131x_isr_handler); | |
905 | ||
906 | /* Determine MAC Address, and copy into the net_device struct */ | |
cfb739b4 GKH |
907 | et131x_setup_hardware_properties(adapter); |
908 | ||
909 | memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN); | |
910 | ||
911 | /* Setup et1310 as per the documentation */ | |
cfb739b4 GKH |
912 | et131x_adapter_setup(adapter); |
913 | ||
914 | /* Create a timer to count errors received by the NIC */ | |
915 | init_timer(&adapter->ErrorTimer); | |
916 | ||
917 | adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; | |
918 | adapter->ErrorTimer.function = et131x_error_timer_handler; | |
919 | adapter->ErrorTimer.data = (unsigned long)adapter; | |
920 | ||
921 | /* Initialize link state */ | |
922 | et131x_link_detection_handler((unsigned long)adapter); | |
923 | ||
64f93036 AC |
924 | /* Intialize variable for counting how long we do not have |
925 | link status */ | |
cfb739b4 GKH |
926 | adapter->PoMgmt.TransPhyComaModeOnBoot = 0; |
927 | ||
928 | /* We can enable interrupts now | |
929 | * | |
930 | * NOTE - Because registration of interrupt handler is done in the | |
931 | * device's open(), defer enabling device interrupts to that | |
932 | * point | |
933 | */ | |
934 | ||
935 | /* Register the net_device struct with the Linux network layer */ | |
64f93036 AC |
936 | result = register_netdev(netdev); |
937 | if (result != 0) { | |
15700039 | 938 | dev_err(&pdev->dev, "register_netdev() failed\n"); |
cfb739b4 GKH |
939 | goto err_mem_free; |
940 | } | |
941 | ||
942 | /* Register the net_device struct with the PCI subsystem. Save a copy | |
943 | * of the PCI config space for this device now that the device has | |
944 | * been initialized, just in case it needs to be quickly restored. | |
945 | */ | |
946 | pci_set_drvdata(pdev, netdev); | |
947 | ||
948 | pci_save_state(adapter->pdev); | |
949 | ||
950 | out: | |
cfb739b4 GKH |
951 | return result; |
952 | ||
953 | err_mem_free: | |
954 | et131x_adapter_memory_free(adapter); | |
955 | err_iounmap: | |
f3f415a3 | 956 | iounmap(adapter->regs); |
cfb739b4 | 957 | err_free_dev: |
6ae56042 | 958 | pci_dev_put(pdev); |
cfb739b4 GKH |
959 | free_netdev(netdev); |
960 | err_release_res: | |
961 | pci_release_regions(pdev); | |
962 | err_disable: | |
963 | pci_disable_device(pdev); | |
964 | goto out; | |
965 | } | |
7ca5d422 AC |
966 | |
967 | static struct pci_device_id et131x_pci_table[] __devinitdata = { | |
968 | {ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_GIG, PCI_ANY_ID, | |
969 | PCI_ANY_ID, 0, 0, 0UL}, | |
970 | {ET131X_PCI_VENDOR_ID, ET131X_PCI_DEVICE_ID_FAST, PCI_ANY_ID, | |
971 | PCI_ANY_ID, 0, 0, 0UL}, | |
972 | {0,} | |
973 | }; | |
974 | ||
975 | MODULE_DEVICE_TABLE(pci, et131x_pci_table); | |
976 | ||
977 | static struct pci_driver et131x_driver = { | |
978 | .name = DRIVER_NAME, | |
979 | .id_table = et131x_pci_table, | |
980 | .probe = et131x_pci_setup, | |
981 | .remove = __devexit_p(et131x_pci_remove), | |
982 | .suspend = NULL, /* et131x_pci_suspend */ | |
983 | .resume = NULL, /* et131x_pci_resume */ | |
984 | }; | |
985 | ||
986 | ||
987 | /** | |
988 | * et131x_init_module - The "main" entry point called on driver initialization | |
989 | * | |
990 | * Returns 0 on success, errno on failure (as defined in errno.h) | |
991 | */ | |
3c0d4464 | 992 | static int __init et131x_init_module(void) |
7ca5d422 AC |
993 | { |
994 | if (et131x_speed_set < PARM_SPEED_DUPLEX_MIN || | |
995 | et131x_speed_set > PARM_SPEED_DUPLEX_MAX) { | |
996 | printk(KERN_WARNING "et131x: invalid speed setting ignored.\n"); | |
997 | et131x_speed_set = 0; | |
998 | } | |
999 | return pci_register_driver(&et131x_driver); | |
1000 | } | |
1001 | ||
1002 | /** | |
1003 | * et131x_cleanup_module - The entry point called on driver cleanup | |
1004 | */ | |
3c0d4464 | 1005 | static void __exit et131x_cleanup_module(void) |
7ca5d422 AC |
1006 | { |
1007 | pci_unregister_driver(&et131x_driver); | |
1008 | } | |
1009 | ||
1010 | module_init(et131x_init_module); | |
1011 | module_exit(et131x_cleanup_module); | |
1012 | ||
1013 | ||
1014 | /* Modinfo parameters (filled out using defines from et131x_version.h) */ | |
1015 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
1016 | MODULE_DESCRIPTION(DRIVER_INFO); | |
1017 | MODULE_LICENSE(DRIVER_LICENSE); |