Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Carsten Langgaard, carstenl@mips.com | |
3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | |
4 | * | |
5 | * ######################################################################## | |
6 | * | |
7 | * This program is free software; you can distribute it and/or modify it | |
8 | * under the terms of the GNU General Public License (Version 2) as | |
9 | * published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along | |
17 | * with this program; if not, write to the Free Software Foundation, Inc., | |
18 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
19 | * | |
20 | * ######################################################################## | |
21 | * | |
22 | * SAA9730 ethernet driver. | |
23 | * | |
24 | * Changes: | |
25 | * Angelo Dell'Aera <buffer@antifork.org> : Conversion to the new PCI API (pci_driver). | |
26 | * Conversion to spinlocks. | |
27 | * Error handling fixes. | |
28 | * | |
29 | */ | |
30 | ||
31 | #include <linux/init.h> | |
32 | #include <linux/netdevice.h> | |
33 | #include <linux/delay.h> | |
34 | #include <linux/etherdevice.h> | |
35 | #include <linux/module.h> | |
36 | #include <linux/skbuff.h> | |
37 | #include <linux/pci.h> | |
38 | #include <linux/spinlock.h> | |
39 | ||
40 | #include <asm/addrspace.h> | |
41 | #include <asm/mips-boards/prom.h> | |
42 | ||
43 | #include "saa9730.h" | |
44 | ||
45 | #ifdef LAN_SAA9730_DEBUG | |
46 | int lan_saa9730_debug = LAN_SAA9730_DEBUG; | |
47 | #else | |
48 | int lan_saa9730_debug; | |
49 | #endif | |
50 | ||
51 | #define DRV_MODULE_NAME "saa9730" | |
52 | ||
53 | static struct pci_device_id saa9730_pci_tbl[] = { | |
54 | { PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9370, | |
55 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | |
56 | { 0, } | |
57 | }; | |
58 | ||
59 | MODULE_DEVICE_TABLE(pci, saa9730_pci_tbl); | |
60 | ||
61 | /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ | |
62 | static unsigned int pci_irq_line; | |
63 | ||
64 | #define INL(a) inl((unsigned long)a) | |
65 | #define OUTL(x,a) outl(x,(unsigned long)a) | |
66 | ||
67 | static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp) | |
68 | { | |
69 | OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, | |
70 | &lp->evm_saa9730_regs->InterruptBlock1); | |
71 | OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, | |
72 | &lp->evm_saa9730_regs->InterruptStatus1); | |
73 | OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | | |
74 | EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); | |
75 | } | |
76 | static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp) | |
77 | { | |
78 | OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, | |
79 | &lp->evm_saa9730_regs->InterruptBlock1); | |
80 | OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, | |
81 | &lp->evm_saa9730_regs->InterruptEnable1); | |
82 | } | |
83 | ||
84 | static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp) | |
85 | { | |
86 | OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); | |
87 | } | |
88 | ||
89 | static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp) | |
90 | { | |
91 | OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, | |
92 | &lp->evm_saa9730_regs->InterruptBlock1); | |
93 | } | |
94 | ||
95 | static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) | |
96 | { | |
97 | OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, | |
98 | &lp->evm_saa9730_regs->InterruptBlock1); | |
99 | } | |
100 | ||
101 | static void show_saa9730_regs(struct lan_saa9730_private *lp) | |
102 | { | |
103 | int i, j; | |
104 | printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]); | |
105 | printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]); | |
106 | printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]); | |
107 | printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]); | |
108 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
109 | for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { | |
110 | printk("TxmBuffer[%d][%d] = %x\n", i, j, | |
111 | le32_to_cpu(*(unsigned int *) | |
112 | lp->TxmBuffer[i][j])); | |
113 | } | |
114 | } | |
115 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
116 | for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) { | |
117 | printk("RcvBuffer[%d][%d] = %x\n", i, j, | |
118 | le32_to_cpu(*(unsigned int *) | |
119 | lp->RcvBuffer[i][j])); | |
120 | } | |
121 | } | |
122 | printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n", | |
123 | INL(&lp->evm_saa9730_regs->InterruptBlock1)); | |
124 | printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n", | |
125 | INL(&lp->evm_saa9730_regs->InterruptStatus1)); | |
126 | printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n", | |
127 | INL(&lp->evm_saa9730_regs->InterruptEnable1)); | |
128 | printk("lp->lan_saa9730_regs->Ok2Use = %x\n", | |
129 | INL(&lp->lan_saa9730_regs->Ok2Use)); | |
130 | printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex); | |
131 | printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex); | |
132 | printk("lp->PendingTxmBufferIndex = %x\n", | |
133 | lp->PendingTxmBufferIndex); | |
134 | printk("lp->PendingTxmPacketIndex = %x\n", | |
135 | lp->PendingTxmPacketIndex); | |
136 | printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n", | |
137 | INL(&lp->lan_saa9730_regs->LanDmaCtl)); | |
138 | printk("lp->lan_saa9730_regs->DmaStatus = %x\n", | |
139 | INL(&lp->lan_saa9730_regs->DmaStatus)); | |
140 | printk("lp->lan_saa9730_regs->CamCtl = %x\n", | |
141 | INL(&lp->lan_saa9730_regs->CamCtl)); | |
142 | printk("lp->lan_saa9730_regs->TxCtl = %x\n", | |
143 | INL(&lp->lan_saa9730_regs->TxCtl)); | |
144 | printk("lp->lan_saa9730_regs->TxStatus = %x\n", | |
145 | INL(&lp->lan_saa9730_regs->TxStatus)); | |
146 | printk("lp->lan_saa9730_regs->RxCtl = %x\n", | |
147 | INL(&lp->lan_saa9730_regs->RxCtl)); | |
148 | printk("lp->lan_saa9730_regs->RxStatus = %x\n", | |
149 | INL(&lp->lan_saa9730_regs->RxStatus)); | |
150 | for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { | |
151 | OUTL(i, &lp->lan_saa9730_regs->CamAddress); | |
152 | printk("lp->lan_saa9730_regs->CamData = %x\n", | |
153 | INL(&lp->lan_saa9730_regs->CamData)); | |
154 | } | |
155 | printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets); | |
156 | printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors); | |
157 | printk("lp->stats.tx_aborted_errors = %lx\n", | |
158 | lp->stats.tx_aborted_errors); | |
159 | printk("lp->stats.tx_window_errors = %lx\n", | |
160 | lp->stats.tx_window_errors); | |
161 | printk("lp->stats.tx_carrier_errors = %lx\n", | |
162 | lp->stats.tx_carrier_errors); | |
163 | printk("lp->stats.tx_fifo_errors = %lx\n", | |
164 | lp->stats.tx_fifo_errors); | |
165 | printk("lp->stats.tx_heartbeat_errors = %lx\n", | |
166 | lp->stats.tx_heartbeat_errors); | |
167 | printk("lp->stats.collisions = %lx\n", lp->stats.collisions); | |
168 | ||
169 | printk("lp->stats.rx_packets = %lx\n", lp->stats.rx_packets); | |
170 | printk("lp->stats.rx_errors = %lx\n", lp->stats.rx_errors); | |
171 | printk("lp->stats.rx_dropped = %lx\n", lp->stats.rx_dropped); | |
172 | printk("lp->stats.rx_crc_errors = %lx\n", lp->stats.rx_crc_errors); | |
173 | printk("lp->stats.rx_frame_errors = %lx\n", | |
174 | lp->stats.rx_frame_errors); | |
175 | printk("lp->stats.rx_fifo_errors = %lx\n", | |
176 | lp->stats.rx_fifo_errors); | |
177 | printk("lp->stats.rx_length_errors = %lx\n", | |
178 | lp->stats.rx_length_errors); | |
179 | ||
180 | printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n", | |
181 | INL(&lp->lan_saa9730_regs->DebugPCIMasterAddr)); | |
182 | printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n", | |
183 | INL(&lp->lan_saa9730_regs->DebugLanTxStateMachine)); | |
184 | printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n", | |
185 | INL(&lp->lan_saa9730_regs->DebugLanRxStateMachine)); | |
186 | printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n", | |
187 | INL(&lp->lan_saa9730_regs->DebugLanTxFifoPointers)); | |
188 | printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n", | |
189 | INL(&lp->lan_saa9730_regs->DebugLanRxFifoPointers)); | |
190 | printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n", | |
191 | INL(&lp->lan_saa9730_regs->DebugLanCtlStateMachine)); | |
192 | } | |
193 | ||
194 | static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp) | |
195 | { | |
196 | int i, j; | |
197 | ||
198 | /* Init RX buffers */ | |
199 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
200 | for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) { | |
201 | *(unsigned int *) lp->RcvBuffer[i][j] = | |
202 | cpu_to_le32(RXSF_READY << | |
203 | RX_STAT_CTL_OWNER_SHF); | |
204 | } | |
205 | } | |
206 | ||
207 | /* Init TX buffers */ | |
208 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
209 | for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { | |
210 | *(unsigned int *) lp->TxmBuffer[i][j] = | |
211 | cpu_to_le32(TXSF_EMPTY << | |
212 | TX_STAT_CTL_OWNER_SHF); | |
213 | } | |
214 | } | |
215 | } | |
216 | ||
217 | static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp) | |
218 | { | |
219 | unsigned int mem_size; | |
220 | void *Pa; | |
221 | unsigned int i, j, RcvBufferSize, TxmBufferSize; | |
222 | unsigned int buffer_start; | |
223 | ||
224 | /* | |
225 | * Allocate all RX and TX packets in one chunk. | |
226 | * The Rx and Tx packets must be PACKET_SIZE aligned. | |
227 | */ | |
228 | mem_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) * | |
229 | LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) + | |
230 | LAN_SAA9730_PACKET_SIZE; | |
231 | buffer_start = | |
232 | (unsigned int) kmalloc(mem_size, GFP_DMA | GFP_KERNEL); | |
233 | ||
234 | if (!buffer_start) | |
235 | return -ENOMEM; | |
236 | ||
237 | /* | |
238 | * Set DMA buffer to kseg1 (uncached). | |
239 | * Make sure to flush before using it uncached. | |
240 | */ | |
241 | Pa = (void *) KSEG1ADDR((buffer_start + LAN_SAA9730_PACKET_SIZE) & | |
242 | ~(LAN_SAA9730_PACKET_SIZE - 1)); | |
243 | dma_cache_wback_inv((unsigned long) Pa, mem_size); | |
244 | ||
245 | /* Initialize buffer space */ | |
246 | RcvBufferSize = LAN_SAA9730_PACKET_SIZE; | |
247 | TxmBufferSize = LAN_SAA9730_PACKET_SIZE; | |
248 | lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE; | |
249 | lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE; | |
250 | ||
251 | /* Init RX buffers */ | |
252 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
253 | for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) { | |
254 | *(unsigned int *) Pa = | |
255 | cpu_to_le32(RXSF_READY << | |
256 | RX_STAT_CTL_OWNER_SHF); | |
257 | lp->RcvBuffer[i][j] = (unsigned int) Pa; | |
258 | Pa += RcvBufferSize; | |
259 | } | |
260 | } | |
261 | ||
262 | /* Init TX buffers */ | |
263 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | |
264 | for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { | |
265 | *(unsigned int *) Pa = | |
266 | cpu_to_le32(TXSF_EMPTY << | |
267 | TX_STAT_CTL_OWNER_SHF); | |
268 | lp->TxmBuffer[i][j] = (unsigned int) Pa; | |
269 | Pa += TxmBufferSize; | |
270 | } | |
271 | } | |
272 | ||
273 | /* | |
274 | * Set rx buffer A and rx buffer B to point to the first two buffer | |
275 | * spaces. | |
276 | */ | |
277 | OUTL(PHYSADDR(lp->RcvBuffer[0][0]), | |
278 | &lp->lan_saa9730_regs->RxBuffA); | |
279 | OUTL(PHYSADDR(lp->RcvBuffer[1][0]), | |
280 | &lp->lan_saa9730_regs->RxBuffB); | |
281 | ||
282 | /* Initialize Buffer Index */ | |
283 | lp->NextRcvPacketIndex = 0; | |
284 | lp->NextRcvToUseIsA = 1; | |
285 | ||
286 | /* Set current buffer index & next availble packet index */ | |
287 | lp->NextTxmPacketIndex = 0; | |
288 | lp->NextTxmBufferIndex = 0; | |
289 | lp->PendingTxmPacketIndex = 0; | |
290 | lp->PendingTxmBufferIndex = 0; | |
291 | ||
292 | /* | |
293 | * Set txm_buf_a and txm_buf_b to point to the first two buffer | |
294 | * space | |
295 | */ | |
296 | OUTL(PHYSADDR(lp->TxmBuffer[0][0]), | |
297 | &lp->lan_saa9730_regs->TxBuffA); | |
298 | OUTL(PHYSADDR(lp->TxmBuffer[1][0]), | |
299 | &lp->lan_saa9730_regs->TxBuffB); | |
300 | ||
301 | /* Set packet number */ | |
302 | OUTL((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | | |
303 | (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | | |
304 | (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | | |
305 | (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), | |
306 | &lp->lan_saa9730_regs->PacketCount); | |
307 | ||
308 | return 0; | |
309 | } | |
310 | ||
311 | static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) | |
312 | { | |
313 | unsigned int i; | |
314 | unsigned char *NetworkAddress; | |
315 | ||
316 | NetworkAddress = (unsigned char *) &lp->PhysicalAddress[0][0]; | |
317 | ||
318 | for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { | |
319 | /* First set address to where data is written */ | |
320 | OUTL(i, &lp->lan_saa9730_regs->CamAddress); | |
321 | OUTL((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) | |
322 | | (NetworkAddress[2] << 8) | NetworkAddress[3], | |
323 | &lp->lan_saa9730_regs->CamData); | |
324 | NetworkAddress += 4; | |
325 | } | |
326 | return 0; | |
327 | } | |
328 | ||
329 | static int lan_saa9730_cam_init(struct net_device *dev) | |
330 | { | |
331 | struct lan_saa9730_private *lp = | |
332 | (struct lan_saa9730_private *) dev->priv; | |
333 | unsigned int i; | |
334 | ||
335 | /* Copy MAC-address into all entries. */ | |
336 | for (i = 0; i < LAN_SAA9730_CAM_ENTRIES; i++) { | |
337 | memcpy((unsigned char *) lp->PhysicalAddress[i], | |
338 | (unsigned char *) dev->dev_addr, 6); | |
339 | } | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
344 | static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) | |
345 | { | |
346 | int i, l; | |
347 | ||
348 | /* Check link status, spin here till station is not busy. */ | |
349 | i = 0; | |
350 | while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) { | |
351 | i++; | |
352 | if (i > 100) { | |
353 | printk("Error: lan_saa9730_mii_init: timeout\n"); | |
354 | return -1; | |
355 | } | |
356 | mdelay(1); /* wait 1 ms. */ | |
357 | } | |
358 | ||
359 | /* Now set the control and address register. */ | |
360 | OUTL(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, | |
361 | &lp->lan_saa9730_regs->StationMgmtCtl); | |
362 | ||
363 | /* check link status, spin here till station is not busy */ | |
364 | i = 0; | |
365 | while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) { | |
366 | i++; | |
367 | if (i > 100) { | |
368 | printk("Error: lan_saa9730_mii_init: timeout\n"); | |
369 | return -1; | |
370 | } | |
371 | mdelay(1); /* wait 1 ms. */ | |
372 | } | |
373 | ||
374 | /* Wait for 1 ms. */ | |
375 | mdelay(1); | |
376 | ||
377 | /* Check the link status. */ | |
378 | if (INL(&lp->lan_saa9730_regs->StationMgmtData) & | |
379 | PHY_STATUS_LINK_UP) { | |
380 | /* Link is up. */ | |
381 | return 0; | |
382 | } else { | |
383 | /* Link is down, reset the PHY first. */ | |
384 | ||
385 | /* set PHY address = 'CONTROL' */ | |
386 | OUTL(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, | |
387 | &lp->lan_saa9730_regs->StationMgmtCtl); | |
388 | ||
389 | /* Wait for 1 ms. */ | |
390 | mdelay(1); | |
391 | ||
392 | /* set 'CONTROL' = force reset and renegotiate */ | |
393 | OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | | |
394 | PHY_CONTROL_RESTART_AUTO_NEG, | |
395 | &lp->lan_saa9730_regs->StationMgmtData); | |
396 | ||
397 | /* Wait for 50 ms. */ | |
398 | mdelay(50); | |
399 | ||
400 | /* set 'BUSY' to start operation */ | |
401 | OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | | |
402 | PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); | |
403 | ||
404 | /* await completion */ | |
405 | i = 0; | |
406 | while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & | |
407 | MD_CA_BUSY) { | |
408 | i++; | |
409 | if (i > 100) { | |
410 | printk | |
411 | ("Error: lan_saa9730_mii_init: timeout\n"); | |
412 | return -1; | |
413 | } | |
414 | mdelay(1); /* wait 1 ms. */ | |
415 | } | |
416 | ||
417 | /* Wait for 1 ms. */ | |
418 | mdelay(1); | |
419 | ||
420 | for (l = 0; l < 2; l++) { | |
421 | /* set PHY address = 'STATUS' */ | |
422 | OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | | |
423 | PHY_STATUS, | |
424 | &lp->lan_saa9730_regs->StationMgmtCtl); | |
425 | ||
426 | /* await completion */ | |
427 | i = 0; | |
428 | while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & | |
429 | MD_CA_BUSY) { | |
430 | i++; | |
431 | if (i > 100) { | |
432 | printk | |
433 | ("Error: lan_saa9730_mii_init: timeout\n"); | |
434 | return -1; | |
435 | } | |
436 | mdelay(1); /* wait 1 ms. */ | |
437 | } | |
438 | ||
439 | /* wait for 3 sec. */ | |
440 | mdelay(3000); | |
441 | ||
442 | /* check the link status */ | |
443 | if (INL(&lp->lan_saa9730_regs->StationMgmtData) & | |
444 | PHY_STATUS_LINK_UP) { | |
445 | /* link is up */ | |
446 | break; | |
447 | } | |
448 | } | |
449 | } | |
450 | ||
451 | return 0; | |
452 | } | |
453 | ||
454 | static int lan_saa9730_control_init(struct lan_saa9730_private *lp) | |
455 | { | |
456 | /* Initialize DMA control register. */ | |
457 | OUTL((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | | |
458 | (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | | |
459 | (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) | |
460 | | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | | |
461 | DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN, | |
462 | &lp->lan_saa9730_regs->LanDmaCtl); | |
463 | ||
464 | /* Initial MAC control register. */ | |
465 | OUTL((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, | |
466 | &lp->lan_saa9730_regs->MacCtl); | |
467 | ||
468 | /* Initialize CAM control register. */ | |
469 | OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, | |
470 | &lp->lan_saa9730_regs->CamCtl); | |
471 | ||
472 | /* | |
473 | * Initialize CAM enable register, only turn on first entry, should | |
474 | * contain own addr. | |
475 | */ | |
476 | OUTL(0x0001, &lp->lan_saa9730_regs->CamEnable); | |
477 | ||
478 | /* Initialize Tx control register */ | |
479 | OUTL(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); | |
480 | ||
481 | /* Initialize Rcv control register */ | |
482 | OUTL(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); | |
483 | ||
484 | /* Reset DMA engine */ | |
485 | OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); | |
486 | ||
487 | return 0; | |
488 | } | |
489 | ||
490 | static int lan_saa9730_stop(struct lan_saa9730_private *lp) | |
491 | { | |
492 | int i; | |
493 | ||
494 | /* Stop DMA first */ | |
495 | OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) & | |
496 | ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), | |
497 | &lp->lan_saa9730_regs->LanDmaCtl); | |
498 | ||
499 | /* Set the SW Reset bits in DMA and MAC control registers */ | |
500 | OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); | |
501 | OUTL(INL(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, | |
502 | &lp->lan_saa9730_regs->MacCtl); | |
503 | ||
504 | /* | |
505 | * Wait for MAC reset to have finished. The reset bit is auto cleared | |
506 | * when the reset is done. | |
507 | */ | |
508 | i = 0; | |
509 | while (INL(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) { | |
510 | i++; | |
511 | if (i > 100) { | |
512 | printk | |
513 | ("Error: lan_sa9730_stop: MAC reset timeout\n"); | |
514 | return -1; | |
515 | } | |
516 | mdelay(1); /* wait 1 ms. */ | |
517 | } | |
518 | ||
519 | return 0; | |
520 | } | |
521 | ||
522 | static int lan_saa9730_dma_init(struct lan_saa9730_private *lp) | |
523 | { | |
524 | /* Stop lan controller. */ | |
525 | lan_saa9730_stop(lp); | |
526 | ||
527 | OUTL(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, | |
528 | &lp->lan_saa9730_regs->Timeout); | |
529 | ||
530 | return 0; | |
531 | } | |
532 | ||
533 | static int lan_saa9730_start(struct lan_saa9730_private *lp) | |
534 | { | |
535 | lan_saa9730_buffer_init(lp); | |
536 | ||
537 | /* Initialize Rx Buffer Index */ | |
538 | lp->NextRcvPacketIndex = 0; | |
539 | lp->NextRcvToUseIsA = 1; | |
540 | ||
541 | /* Set current buffer index & next availble packet index */ | |
542 | lp->NextTxmPacketIndex = 0; | |
543 | lp->NextTxmBufferIndex = 0; | |
544 | lp->PendingTxmPacketIndex = 0; | |
545 | lp->PendingTxmBufferIndex = 0; | |
546 | ||
547 | OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | | |
548 | DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); | |
549 | ||
550 | /* For Tx, turn on MAC then DMA */ | |
551 | OUTL(INL(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, | |
552 | &lp->lan_saa9730_regs->TxCtl); | |
553 | ||
554 | /* For Rx, turn on DMA then MAC */ | |
555 | OUTL(INL(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, | |
556 | &lp->lan_saa9730_regs->RxCtl); | |
557 | ||
558 | /* Set Ok2Use to let hardware owns the buffers */ | |
559 | OUTL(OK2USE_RX_A | OK2USE_RX_B | OK2USE_TX_A | OK2USE_TX_B, | |
560 | &lp->lan_saa9730_regs->Ok2Use); | |
561 | ||
562 | return 0; | |
563 | } | |
564 | ||
565 | static int lan_saa9730_restart(struct lan_saa9730_private *lp) | |
566 | { | |
567 | lan_saa9730_stop(lp); | |
568 | lan_saa9730_start(lp); | |
569 | ||
570 | return 0; | |
571 | } | |
572 | ||
573 | static int lan_saa9730_tx(struct net_device *dev) | |
574 | { | |
575 | struct lan_saa9730_private *lp = | |
576 | (struct lan_saa9730_private *) dev->priv; | |
577 | unsigned int *pPacket; | |
578 | unsigned int tx_status; | |
579 | ||
580 | if (lan_saa9730_debug > 5) | |
581 | printk("lan_saa9730_tx interrupt\n"); | |
582 | ||
583 | /* Clear interrupt. */ | |
584 | OUTL(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); | |
585 | ||
586 | while (1) { | |
587 | pPacket = | |
588 | (unsigned int *) lp->TxmBuffer[lp-> | |
589 | PendingTxmBufferIndex] | |
590 | [lp->PendingTxmPacketIndex]; | |
591 | ||
592 | /* Get status of first packet transmitted. */ | |
593 | tx_status = le32_to_cpu(*pPacket); | |
594 | ||
595 | /* Check ownership. */ | |
596 | if ((tx_status & TX_STAT_CTL_OWNER_MSK) != | |
597 | (TXSF_HWDONE << TX_STAT_CTL_OWNER_SHF)) break; | |
598 | ||
599 | /* Check for error. */ | |
600 | if (tx_status & TX_STAT_CTL_ERROR_MSK) { | |
601 | if (lan_saa9730_debug > 1) | |
602 | printk("lan_saa9730_tx: tx error = %x\n", | |
603 | tx_status); | |
604 | ||
605 | lp->stats.tx_errors++; | |
606 | if (tx_status & | |
607 | (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF)) | |
608 | lp->stats.tx_aborted_errors++; | |
609 | if (tx_status & | |
610 | (TX_STATUS_LATE_COLL << | |
611 | TX_STAT_CTL_STATUS_SHF)) lp->stats. | |
612 | tx_window_errors++; | |
613 | if (tx_status & | |
614 | (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF)) | |
615 | lp->stats.tx_carrier_errors++; | |
616 | if (tx_status & | |
617 | (TX_STATUS_UNDER << TX_STAT_CTL_STATUS_SHF)) | |
618 | lp->stats.tx_fifo_errors++; | |
619 | if (tx_status & | |
620 | (TX_STATUS_SQ_ERR << TX_STAT_CTL_STATUS_SHF)) | |
621 | lp->stats.tx_heartbeat_errors++; | |
622 | ||
623 | lp->stats.collisions += | |
624 | tx_status & TX_STATUS_TX_COLL_MSK; | |
625 | } | |
626 | ||
627 | /* Free buffer. */ | |
628 | *pPacket = | |
629 | cpu_to_le32(TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF); | |
630 | ||
631 | /* Update pending index pointer. */ | |
632 | lp->PendingTxmPacketIndex++; | |
633 | if (lp->PendingTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) { | |
634 | lp->PendingTxmPacketIndex = 0; | |
635 | lp->PendingTxmBufferIndex ^= 1; | |
636 | } | |
637 | } | |
638 | ||
639 | /* Make sure A and B are available to hardware. */ | |
640 | OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use); | |
641 | ||
642 | if (netif_queue_stopped(dev)) { | |
643 | /* The tx buffer is no longer full. */ | |
644 | netif_wake_queue(dev); | |
645 | } | |
646 | ||
647 | return 0; | |
648 | } | |
649 | ||
650 | static int lan_saa9730_rx(struct net_device *dev) | |
651 | { | |
652 | struct lan_saa9730_private *lp = | |
653 | (struct lan_saa9730_private *) dev->priv; | |
654 | int len = 0; | |
655 | struct sk_buff *skb = 0; | |
656 | unsigned int rx_status; | |
657 | int BufferIndex; | |
658 | int PacketIndex; | |
659 | unsigned int *pPacket; | |
660 | unsigned char *pData; | |
661 | ||
662 | if (lan_saa9730_debug > 5) | |
663 | printk("lan_saa9730_rx interrupt\n"); | |
664 | ||
665 | /* Clear receive interrupts. */ | |
666 | OUTL(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | | |
667 | DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); | |
668 | ||
669 | /* Address next packet */ | |
670 | if (lp->NextRcvToUseIsA) | |
671 | BufferIndex = 0; | |
672 | else | |
673 | BufferIndex = 1; | |
674 | PacketIndex = lp->NextRcvPacketIndex; | |
675 | pPacket = (unsigned int *) lp->RcvBuffer[BufferIndex][PacketIndex]; | |
676 | rx_status = le32_to_cpu(*pPacket); | |
677 | ||
678 | /* Process each packet. */ | |
679 | while ((rx_status & RX_STAT_CTL_OWNER_MSK) == | |
680 | (RXSF_HWDONE << RX_STAT_CTL_OWNER_SHF)) { | |
681 | /* Check the rx status. */ | |
682 | if (rx_status & (RX_STATUS_GOOD << RX_STAT_CTL_STATUS_SHF)) { | |
683 | /* Received packet is good. */ | |
684 | len = (rx_status & RX_STAT_CTL_LENGTH_MSK) >> | |
685 | RX_STAT_CTL_LENGTH_SHF; | |
686 | ||
687 | pData = (unsigned char *) pPacket; | |
688 | pData += 4; | |
689 | skb = dev_alloc_skb(len + 2); | |
690 | if (skb == 0) { | |
691 | printk | |
692 | ("%s: Memory squeeze, deferring packet.\n", | |
693 | dev->name); | |
694 | lp->stats.rx_dropped++; | |
695 | } else { | |
696 | lp->stats.rx_bytes += len; | |
697 | lp->stats.rx_packets++; | |
698 | skb->dev = dev; | |
699 | skb_reserve(skb, 2); /* 16 byte align */ | |
700 | skb_put(skb, len); /* make room */ | |
701 | eth_copy_and_sum(skb, | |
702 | (unsigned char *) pData, | |
703 | len, 0); | |
704 | skb->protocol = eth_type_trans(skb, dev); | |
705 | netif_rx(skb); | |
706 | dev->last_rx = jiffies; | |
707 | } | |
708 | } else { | |
709 | /* We got an error packet. */ | |
710 | if (lan_saa9730_debug > 2) | |
711 | printk | |
712 | ("lan_saa9730_rx: We got an error packet = %x\n", | |
713 | rx_status); | |
714 | ||
715 | lp->stats.rx_errors++; | |
716 | if (rx_status & | |
717 | (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF)) | |
718 | lp->stats.rx_crc_errors++; | |
719 | if (rx_status & | |
720 | (RX_STATUS_ALIGN_ERR << | |
721 | RX_STAT_CTL_STATUS_SHF)) lp->stats. | |
722 | rx_frame_errors++; | |
723 | if (rx_status & | |
724 | (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF)) | |
725 | lp->stats.rx_fifo_errors++; | |
726 | if (rx_status & | |
727 | (RX_STATUS_LONG_ERR << RX_STAT_CTL_STATUS_SHF)) | |
728 | lp->stats.rx_length_errors++; | |
729 | } | |
730 | ||
731 | /* Indicate we have processed the buffer. */ | |
732 | *pPacket = | |
733 | cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF); | |
734 | ||
735 | /* Go to next packet in sequence. */ | |
736 | lp->NextRcvPacketIndex++; | |
737 | if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) { | |
738 | lp->NextRcvPacketIndex = 0; | |
739 | if (BufferIndex) { | |
740 | lp->NextRcvToUseIsA = 1; | |
741 | } else { | |
742 | lp->NextRcvToUseIsA = 0; | |
743 | } | |
744 | } | |
745 | OUTL(OK2USE_RX_A | OK2USE_RX_B, | |
746 | &lp->lan_saa9730_regs->Ok2Use); | |
747 | ||
748 | /* Address next packet */ | |
749 | if (lp->NextRcvToUseIsA) | |
750 | BufferIndex = 0; | |
751 | else | |
752 | BufferIndex = 1; | |
753 | PacketIndex = lp->NextRcvPacketIndex; | |
754 | pPacket = | |
755 | (unsigned int *) lp-> | |
756 | RcvBuffer[BufferIndex][PacketIndex]; | |
757 | rx_status = le32_to_cpu(*pPacket); | |
758 | } | |
759 | ||
760 | /* Make sure A and B are available to hardware. */ | |
761 | OUTL(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use); | |
762 | ||
763 | return 0; | |
764 | } | |
765 | ||
766 | static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, | |
767 | struct pt_regs *regs) | |
768 | { | |
769 | struct net_device *dev = (struct net_device *) dev_id; | |
770 | struct lan_saa9730_private *lp = | |
771 | (struct lan_saa9730_private *) dev->priv; | |
772 | ||
773 | if (lan_saa9730_debug > 5) | |
774 | printk("lan_saa9730_interrupt\n"); | |
775 | ||
776 | /* Disable the EVM LAN interrupt. */ | |
777 | evm_saa9730_block_lan_int(lp); | |
778 | ||
779 | /* Clear the EVM LAN interrupt. */ | |
780 | evm_saa9730_clear_lan_int(lp); | |
781 | ||
782 | /* Service pending transmit interrupts. */ | |
783 | if (INL(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT) | |
784 | lan_saa9730_tx(dev); | |
785 | ||
786 | /* Service pending receive interrupts. */ | |
787 | if (INL(&lp->lan_saa9730_regs->DmaStatus) & | |
788 | (DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | | |
789 | DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev); | |
790 | ||
791 | /* Enable the EVM LAN interrupt. */ | |
792 | evm_saa9730_unblock_lan_int(lp); | |
793 | ||
794 | return IRQ_HANDLED; | |
795 | } | |
796 | ||
797 | static int lan_saa9730_open_fail(struct net_device *dev) | |
798 | { | |
799 | return -ENODEV; | |
800 | } | |
801 | ||
802 | static int lan_saa9730_open(struct net_device *dev) | |
803 | { | |
804 | struct lan_saa9730_private *lp = | |
805 | (struct lan_saa9730_private *) dev->priv; | |
806 | ||
807 | /* Associate IRQ with lan_saa9730_interrupt */ | |
808 | if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth", | |
809 | dev)) { | |
810 | printk("lan_saa9730_open: Can't get irq %d\n", dev->irq); | |
811 | return -EAGAIN; | |
812 | } | |
813 | ||
814 | /* Enable the Lan interrupt in the event manager. */ | |
815 | evm_saa9730_enable_lan_int(lp); | |
816 | ||
817 | /* Start the LAN controller */ | |
818 | if (lan_saa9730_start(lp)) | |
819 | return -1; | |
820 | ||
821 | netif_start_queue(dev); | |
822 | ||
823 | return 0; | |
824 | } | |
825 | ||
826 | static int lan_saa9730_write(struct lan_saa9730_private *lp, | |
827 | struct sk_buff *skb, int skblen) | |
828 | { | |
829 | unsigned char *pbData = skb->data; | |
830 | unsigned int len = skblen; | |
831 | unsigned char *pbPacketData; | |
832 | unsigned int tx_status; | |
833 | int BufferIndex; | |
834 | int PacketIndex; | |
835 | ||
836 | if (lan_saa9730_debug > 5) | |
837 | printk("lan_saa9730_write: skb=%08x\n", | |
838 | (unsigned int) skb); | |
839 | ||
840 | BufferIndex = lp->NextTxmBufferIndex; | |
841 | PacketIndex = lp->NextTxmPacketIndex; | |
842 | ||
843 | tx_status = | |
844 | le32_to_cpu(*(unsigned int *) lp-> | |
845 | TxmBuffer[BufferIndex][PacketIndex]); | |
846 | if ((tx_status & TX_STAT_CTL_OWNER_MSK) != | |
847 | (TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) { | |
848 | if (lan_saa9730_debug > 4) | |
849 | printk | |
850 | ("lan_saa9730_write: Tx buffer not available: tx_status = %x\n", | |
851 | tx_status); | |
852 | return -1; | |
853 | } | |
854 | ||
855 | lp->NextTxmPacketIndex++; | |
856 | if (lp->NextTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) { | |
857 | lp->NextTxmPacketIndex = 0; | |
858 | lp->NextTxmBufferIndex ^= 1; | |
859 | } | |
860 | ||
861 | pbPacketData = | |
862 | (unsigned char *) lp->TxmBuffer[BufferIndex][PacketIndex]; | |
863 | pbPacketData += 4; | |
864 | ||
865 | /* copy the bits */ | |
866 | memcpy(pbPacketData, pbData, len); | |
867 | ||
868 | /* Set transmit status for hardware */ | |
869 | *(unsigned int *) lp->TxmBuffer[BufferIndex][PacketIndex] = | |
870 | cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) | | |
871 | (TX_STAT_CTL_INT_AFTER_TX << TX_STAT_CTL_FRAME_SHF) | |
872 | | (len << TX_STAT_CTL_LENGTH_SHF)); | |
873 | ||
874 | /* Set hardware tx buffer. */ | |
875 | OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use); | |
876 | ||
877 | return 0; | |
878 | } | |
879 | ||
880 | static void lan_saa9730_tx_timeout(struct net_device *dev) | |
881 | { | |
882 | struct lan_saa9730_private *lp = | |
883 | (struct lan_saa9730_private *) dev->priv; | |
884 | ||
885 | /* Transmitter timeout, serious problems */ | |
886 | lp->stats.tx_errors++; | |
887 | printk("%s: transmit timed out, reset\n", dev->name); | |
888 | /*show_saa9730_regs(lp); */ | |
889 | lan_saa9730_restart(lp); | |
890 | ||
891 | dev->trans_start = jiffies; | |
892 | netif_start_queue(dev); | |
893 | } | |
894 | ||
895 | static int lan_saa9730_start_xmit(struct sk_buff *skb, | |
896 | struct net_device *dev) | |
897 | { | |
898 | struct lan_saa9730_private *lp = | |
899 | (struct lan_saa9730_private *) dev->priv; | |
900 | unsigned long flags; | |
901 | int skblen; | |
902 | int len; | |
903 | ||
904 | if (lan_saa9730_debug > 4) | |
905 | printk("Send packet: skb=%08x\n", (unsigned int) skb); | |
906 | ||
907 | skblen = skb->len; | |
908 | ||
909 | spin_lock_irqsave(&lp->lock, flags); | |
910 | ||
911 | len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; | |
912 | ||
913 | if (lan_saa9730_write(lp, skb, skblen)) { | |
914 | spin_unlock_irqrestore(&lp->lock, flags); | |
915 | printk("Error when writing packet to controller: skb=%08x\n", | |
916 | (unsigned int) skb); | |
917 | netif_stop_queue(dev); | |
918 | return -1; | |
919 | } | |
920 | ||
921 | lp->stats.tx_bytes += len; | |
922 | lp->stats.tx_packets++; | |
923 | ||
924 | dev->trans_start = jiffies; | |
925 | netif_start_queue(dev); | |
926 | dev_kfree_skb(skb); | |
927 | ||
928 | spin_unlock_irqrestore(&lp->lock, flags); | |
929 | ||
930 | return 0; | |
931 | } | |
932 | ||
933 | static int lan_saa9730_close(struct net_device *dev) | |
934 | { | |
935 | struct lan_saa9730_private *lp = | |
936 | (struct lan_saa9730_private *) dev->priv; | |
937 | ||
938 | if (lan_saa9730_debug > 1) | |
939 | printk("lan_saa9730_close:\n"); | |
940 | ||
941 | netif_stop_queue(dev); | |
942 | ||
943 | /* Disable the Lan interrupt in the event manager. */ | |
944 | evm_saa9730_disable_lan_int(lp); | |
945 | ||
946 | /* Stop the controller */ | |
947 | if (lan_saa9730_stop(lp)) | |
948 | return -1; | |
949 | ||
950 | free_irq(dev->irq, (void *) dev); | |
951 | ||
952 | return 0; | |
953 | } | |
954 | ||
955 | static struct net_device_stats *lan_saa9730_get_stats(struct net_device | |
956 | *dev) | |
957 | { | |
958 | struct lan_saa9730_private *lp = | |
959 | (struct lan_saa9730_private *) dev->priv; | |
960 | ||
961 | return &lp->stats; | |
962 | } | |
963 | ||
964 | static void lan_saa9730_set_multicast(struct net_device *dev) | |
965 | { | |
966 | struct lan_saa9730_private *lp = | |
967 | (struct lan_saa9730_private *) dev->priv; | |
968 | ||
969 | /* Stop the controller */ | |
970 | lan_saa9730_stop(lp); | |
971 | ||
972 | if (dev->flags & IFF_PROMISC) { | |
973 | /* accept all packets */ | |
974 | OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | | |
975 | CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, | |
976 | &lp->lan_saa9730_regs->CamCtl); | |
977 | } else { | |
978 | if (dev->flags & IFF_ALLMULTI) { | |
979 | /* accept all multicast packets */ | |
980 | OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | | |
981 | CAM_CONTROL_BROAD_ACC, | |
982 | &lp->lan_saa9730_regs->CamCtl); | |
983 | } else { | |
984 | /* | |
985 | * Will handle the multicast stuff later. -carstenl | |
986 | */ | |
987 | } | |
988 | } | |
989 | ||
990 | lan_saa9730_restart(lp); | |
991 | } | |
992 | ||
993 | ||
994 | static void __devexit saa9730_remove_one(struct pci_dev *pdev) | |
995 | { | |
996 | struct net_device *dev = pci_get_drvdata(pdev); | |
997 | ||
998 | if (dev) { | |
999 | unregister_netdev(dev); | |
1000 | ||
1001 | if (dev->priv) | |
1002 | kfree(dev->priv); | |
1003 | ||
1004 | free_netdev(dev); | |
1005 | pci_release_regions(pdev); | |
1006 | pci_disable_device(pdev); | |
1007 | pci_set_drvdata(pdev, NULL); | |
1008 | } | |
1009 | } | |
1010 | ||
1011 | ||
1012 | static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq) | |
1013 | { | |
1014 | struct lan_saa9730_private *lp; | |
1015 | unsigned char ethernet_addr[6]; | |
1016 | int ret = 0; | |
1017 | ||
1018 | dev->open = lan_saa9730_open_fail; | |
1019 | ||
1020 | if (get_ethernet_addr(ethernet_addr)) | |
1021 | return -ENODEV; | |
1022 | ||
1023 | memcpy(dev->dev_addr, ethernet_addr, 6); | |
1024 | dev->base_addr = ioaddr; | |
1025 | dev->irq = irq; | |
1026 | ||
1027 | /* | |
1028 | * Make certain the data structures used by the controller are aligned | |
1029 | * and DMAble. | |
1030 | */ | |
1031 | /* | |
1032 | * XXX: that is obviously broken - kfree() won't be happy with us. | |
1033 | */ | |
1034 | lp = (struct lan_saa9730_private *) (((unsigned long) | |
1035 | kmalloc(sizeof(*lp) + 7, | |
1036 | GFP_DMA | GFP_KERNEL) | |
1037 | + 7) & ~7); | |
1038 | ||
1039 | if (!lp) | |
1040 | return -ENOMEM; | |
1041 | ||
1042 | dev->priv = lp; | |
1043 | memset(lp, 0, sizeof(*lp)); | |
1044 | ||
1045 | /* Set SAA9730 LAN base address. */ | |
1046 | lp->lan_saa9730_regs = (t_lan_saa9730_regmap *) (ioaddr + | |
1047 | SAA9730_LAN_REGS_ADDR); | |
1048 | ||
1049 | /* Set SAA9730 EVM base address. */ | |
1050 | lp->evm_saa9730_regs = (t_evm_saa9730_regmap *) (ioaddr + | |
1051 | SAA9730_EVM_REGS_ADDR); | |
1052 | ||
1053 | /* Allocate LAN RX/TX frame buffer space. */ | |
1054 | /* FIXME: a leak */ | |
1055 | if ((ret = lan_saa9730_allocate_buffers(lp))) | |
1056 | goto out; | |
1057 | ||
1058 | /* Stop LAN controller. */ | |
1059 | if ((ret = lan_saa9730_stop(lp))) | |
1060 | goto out; | |
1061 | ||
1062 | /* Initialize CAM registers. */ | |
1063 | if ((ret = lan_saa9730_cam_init(dev))) | |
1064 | goto out; | |
1065 | ||
1066 | /* Initialize MII registers. */ | |
1067 | if ((ret = lan_saa9730_mii_init(lp))) | |
1068 | goto out; | |
1069 | ||
1070 | /* Initialize control registers. */ | |
1071 | if ((ret = lan_saa9730_control_init(lp))) | |
1072 | goto out; | |
1073 | ||
1074 | /* Load CAM registers. */ | |
1075 | if ((ret = lan_saa9730_cam_load(lp))) | |
1076 | goto out; | |
1077 | ||
1078 | /* Initialize DMA context registers. */ | |
1079 | if ((ret = lan_saa9730_dma_init(lp))) | |
1080 | goto out; | |
1081 | ||
1082 | spin_lock_init(&lp->lock); | |
1083 | ||
1084 | dev->open = lan_saa9730_open; | |
1085 | dev->hard_start_xmit = lan_saa9730_start_xmit; | |
1086 | dev->stop = lan_saa9730_close; | |
1087 | dev->get_stats = lan_saa9730_get_stats; | |
1088 | dev->set_multicast_list = lan_saa9730_set_multicast; | |
1089 | dev->tx_timeout = lan_saa9730_tx_timeout; | |
1090 | dev->watchdog_timeo = (HZ >> 1); | |
1091 | dev->dma = 0; | |
1092 | ||
1093 | ret = register_netdev(dev); | |
1094 | if (ret) | |
1095 | goto out; | |
1096 | return 0; | |
1097 | ||
1098 | out: | |
1099 | if (dev->priv) | |
1100 | kfree(dev->priv); | |
1101 | return ret; | |
1102 | } | |
1103 | ||
1104 | ||
1105 | static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |
1106 | { | |
1107 | struct net_device *dev; | |
1108 | unsigned int pci_ioaddr; | |
1109 | int err; | |
1110 | ||
1111 | if (lan_saa9730_debug > 1) | |
1112 | printk("saa9730.c: PCI bios is present, checking for devices...\n"); | |
1113 | ||
1114 | err = -ENOMEM; | |
1115 | dev = alloc_etherdev(0); | |
1116 | if (!dev) | |
1117 | goto out; | |
1118 | ||
1119 | SET_MODULE_OWNER(dev); | |
1120 | ||
1121 | err = pci_enable_device(pdev); | |
1122 | if (err) { | |
1123 | printk(KERN_ERR "Cannot enable PCI device, aborting.\n"); | |
1124 | goto out1; | |
1125 | } | |
1126 | ||
1127 | err = pci_request_regions(pdev, DRV_MODULE_NAME); | |
1128 | if (err) { | |
1129 | printk(KERN_ERR "Cannot obtain PCI resources, aborting.\n"); | |
1130 | goto out2; | |
1131 | } | |
1132 | ||
1133 | pci_irq_line = pdev->irq; | |
1134 | /* LAN base address in located at BAR 1. */ | |
1135 | ||
1136 | pci_ioaddr = pci_resource_start(pdev, 1); | |
1137 | pci_set_master(pdev); | |
1138 | ||
1139 | printk("Found SAA9730 (PCI) at %#x, irq %d.\n", | |
1140 | pci_ioaddr, pci_irq_line); | |
1141 | ||
1142 | err = lan_saa9730_init(dev, pci_ioaddr, pci_irq_line); | |
1143 | if (err) { | |
1144 | printk("Lan init failed"); | |
1145 | goto out2; | |
1146 | } | |
1147 | ||
1148 | pci_set_drvdata(pdev, dev); | |
1149 | SET_NETDEV_DEV(dev, &pdev->dev); | |
1150 | return 0; | |
1151 | ||
1152 | out2: | |
1153 | pci_disable_device(pdev); | |
1154 | out1: | |
1155 | free_netdev(dev); | |
1156 | out: | |
1157 | return err; | |
1158 | } | |
1159 | ||
1160 | ||
1161 | static struct pci_driver saa9730_driver = { | |
1162 | .name = DRV_MODULE_NAME, | |
1163 | .id_table = saa9730_pci_tbl, | |
1164 | .probe = saa9730_init_one, | |
1165 | .remove = __devexit_p(saa9730_remove_one), | |
1166 | }; | |
1167 | ||
1168 | ||
1169 | static int __init saa9730_init(void) | |
1170 | { | |
1171 | return pci_module_init(&saa9730_driver); | |
1172 | } | |
1173 | ||
1174 | static void __exit saa9730_cleanup(void) | |
1175 | { | |
1176 | pci_unregister_driver(&saa9730_driver); | |
1177 | } | |
1178 | ||
1179 | module_init(saa9730_init); | |
1180 | module_exit(saa9730_cleanup); | |
1181 | ||
1182 | ||
1183 | ||
1184 | MODULE_LICENSE("GPL"); |