Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / intelx.c
1 /*
2  * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdint.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <byteswap.h>
27 #include <ipxe/netdevice.h>
28 #include <ipxe/ethernet.h>
29 #include <ipxe/if_ether.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/malloc.h>
32 #include <ipxe/pci.h>
33 #include "intelx.h"
34
35 /** @file
36  *
37  * Intel 10 Gigabit Ethernet network card driver
38  *
39  */
40
41 /******************************************************************************
42  *
43  * MAC address
44  *
45  ******************************************************************************
46  */
47
48 /**
49  * Try to fetch initial MAC address
50  *
51  * @v intel             Intel device
52  * @v ral0              RAL0 register address
53  * @v hw_addr           Hardware address to fill in
54  * @ret rc              Return status code
55  */
56 static int intelx_try_fetch_mac ( struct intel_nic *intel, unsigned int ral0,
57                                   uint8_t *hw_addr ) {
58         union intel_receive_address mac;
59
60         /* Read current address from RAL0/RAH0 */
61         mac.reg.low = cpu_to_le32 ( readl ( intel->regs + ral0 ) );
62         mac.reg.high = cpu_to_le32 ( readl ( intel->regs + ral0 +
63                                              ( INTELX_RAH0 - INTELX_RAL0 ) ) );
64
65         /* Use current address if valid */
66         if ( is_valid_ether_addr ( mac.raw ) ) {
67                 DBGC ( intel, "INTEL %p has autoloaded MAC address %s at "
68                        "%#05x\n", intel, eth_ntoa ( mac.raw ), ral0 );
69                 memcpy ( hw_addr, mac.raw, ETH_ALEN );
70                 return 0;
71         }
72
73         return -ENOENT;
74 }
75
76 /**
77  * Fetch initial MAC address
78  *
79  * @v intel             Intel device
80  * @v hw_addr           Hardware address to fill in
81  * @ret rc              Return status code
82  */
83 static int intelx_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) {
84         int rc;
85
86         /* Try to fetch address from INTELX_RAL0 */
87         if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0,
88                                            hw_addr ) ) == 0 ) {
89                 return 0;
90         }
91
92         /* Try to fetch address from INTELX_RAL0_ALT */
93         if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0_ALT,
94                                            hw_addr ) ) == 0 ) {
95                 return 0;
96         }
97
98         DBGC ( intel, "INTEL %p has no MAC address to use\n", intel );
99         return -ENOENT;
100 }
101
102 /******************************************************************************
103  *
104  * Device reset
105  *
106  ******************************************************************************
107  */
108
109 /**
110  * Reset hardware
111  *
112  * @v intel             Intel device
113  * @ret rc              Return status code
114  */
115 static int intelx_reset ( struct intel_nic *intel ) {
116         uint32_t ctrl;
117
118         /* Perform a global software reset */
119         ctrl = readl ( intel->regs + INTELX_CTRL );
120         writel ( ( ctrl | INTELX_CTRL_RST | INTELX_CTRL_LRST ),
121                  intel->regs + INTELX_CTRL );
122         mdelay ( INTELX_RESET_DELAY_MS );
123
124         DBGC ( intel, "INTEL %p reset (ctrl %08x)\n", intel, ctrl );
125         return 0;
126 }
127
128 /******************************************************************************
129  *
130  * Link state
131  *
132  ******************************************************************************
133  */
134
135 /**
136  * Check link state
137  *
138  * @v netdev            Network device
139  */
140 static void intelx_check_link ( struct net_device *netdev ) {
141         struct intel_nic *intel = netdev->priv;
142         uint32_t links;
143
144         /* Read link status */
145         links = readl ( intel->regs + INTELX_LINKS );
146         DBGC ( intel, "INTEL %p link status is %08x\n", intel, links );
147
148         /* Update network device */
149         if ( links & INTELX_LINKS_UP ) {
150                 netdev_link_up ( netdev );
151         } else {
152                 netdev_link_down ( netdev );
153         }
154 }
155
156 /******************************************************************************
157  *
158  * Network device interface
159  *
160  ******************************************************************************
161  */
162
163 /**
164  * Open network device
165  *
166  * @v netdev            Network device
167  * @ret rc              Return status code
168  */
169 static int intelx_open ( struct net_device *netdev ) {
170         struct intel_nic *intel = netdev->priv;
171         union intel_receive_address mac;
172         uint32_t ral0;
173         uint32_t rah0;
174         uint32_t dmatxctl;
175         uint32_t fctrl;
176         uint32_t srrctl;
177         uint32_t hlreg0;
178         uint32_t maxfrs;
179         uint32_t rdrxctl;
180         uint32_t rxctrl;
181         uint32_t dca_rxctrl;
182         int rc;
183
184         /* Create transmit descriptor ring */
185         if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
186                 goto err_create_tx;
187
188         /* Create receive descriptor ring */
189         if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 )
190                 goto err_create_rx;
191
192         /* Program MAC address */
193         memset ( &mac, 0, sizeof ( mac ) );
194         memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) );
195         ral0 = le32_to_cpu ( mac.reg.low );
196         rah0 = ( le32_to_cpu ( mac.reg.high ) | INTELX_RAH0_AV );
197         writel ( ral0, intel->regs + INTELX_RAL0 );
198         writel ( rah0, intel->regs + INTELX_RAH0 );
199         writel ( ral0, intel->regs + INTELX_RAL0_ALT );
200         writel ( rah0, intel->regs + INTELX_RAH0_ALT );
201
202         /* Allocate interrupt vectors */
203         writel ( ( INTELX_IVAR_RX0_DEFAULT | INTELX_IVAR_RX0_VALID |
204                    INTELX_IVAR_TX0_DEFAULT | INTELX_IVAR_TX0_VALID ),
205                  intel->regs + INTELX_IVAR );
206
207         /* Enable transmitter  */
208         dmatxctl = readl ( intel->regs + INTELX_DMATXCTL );
209         dmatxctl |= INTELX_DMATXCTL_TE;
210         writel ( dmatxctl, intel->regs + INTELX_DMATXCTL );
211
212         /* Configure receive filter */
213         fctrl = readl ( intel->regs + INTELX_FCTRL );
214         fctrl |= ( INTELX_FCTRL_BAM | INTELX_FCTRL_UPE | INTELX_FCTRL_MPE );
215         writel ( fctrl, intel->regs + INTELX_FCTRL );
216
217         /* Configure receive buffer sizes */
218         srrctl = readl ( intel->regs + INTELX_SRRCTL );
219         srrctl &= ~INTELX_SRRCTL_BSIZE_MASK;
220         srrctl |= INTELX_SRRCTL_BSIZE_DEFAULT;
221         writel ( srrctl, intel->regs + INTELX_SRRCTL );
222
223         /* Configure jumbo frames.  Required to allow the extra 4-byte
224          * headroom for VLANs, since we don't use the hardware's
225          * native VLAN offload.
226          */
227         hlreg0 = readl ( intel->regs + INTELX_HLREG0 );
228         hlreg0 |= INTELX_HLREG0_JUMBOEN;
229         writel ( hlreg0, intel->regs + INTELX_HLREG0 );
230
231         /* Configure frame size */
232         maxfrs = readl ( intel->regs + INTELX_MAXFRS );
233         maxfrs &= ~INTELX_MAXFRS_MFS_MASK;
234         maxfrs |= INTELX_MAXFRS_MFS_DEFAULT;
235         writel ( maxfrs, intel->regs + INTELX_MAXFRS );
236
237         /* Configure receive DMA */
238         rdrxctl = readl ( intel->regs + INTELX_RDRXCTL );
239         rdrxctl |= INTELX_RDRXCTL_SECRC;
240         writel ( rdrxctl, intel->regs + INTELX_RDRXCTL );
241
242         /* Clear "must-be-zero" bit for direct cache access (DCA).  We
243          * leave DCA disabled anyway, but if we do not clear this bit
244          * then the received packets contain garbage data.
245          */
246         dca_rxctrl = readl ( intel->regs + INTELX_DCA_RXCTRL );
247         dca_rxctrl &= ~INTELX_DCA_RXCTRL_MUST_BE_ZERO;
248         writel ( dca_rxctrl, intel->regs + INTELX_DCA_RXCTRL );
249
250         /* Enable receiver */
251         rxctrl = readl ( intel->regs + INTELX_RXCTRL );
252         rxctrl |= INTELX_RXCTRL_RXEN;
253         writel ( rxctrl, intel->regs + INTELX_RXCTRL );
254
255         /* Fill receive ring */
256         intel_refill_rx ( intel );
257
258         /* Update link state */
259         intelx_check_link ( netdev );
260
261         return 0;
262
263         intel_destroy_ring ( intel, &intel->rx );
264  err_create_rx:
265         intel_destroy_ring ( intel, &intel->tx );
266  err_create_tx:
267         return rc;
268 }
269
270 /**
271  * Close network device
272  *
273  * @v netdev            Network device
274  */
275 static void intelx_close ( struct net_device *netdev ) {
276         struct intel_nic *intel = netdev->priv;
277         uint32_t rxctrl;
278         uint32_t dmatxctl;
279
280         /* Disable receiver */
281         rxctrl = readl ( intel->regs + INTELX_RXCTRL );
282         rxctrl &= ~INTELX_RXCTRL_RXEN;
283         writel ( rxctrl, intel->regs + INTELX_RXCTRL );
284
285         /* Disable transmitter  */
286         dmatxctl = readl ( intel->regs + INTELX_DMATXCTL );
287         dmatxctl &= ~INTELX_DMATXCTL_TE;
288         writel ( dmatxctl, intel->regs + INTELX_DMATXCTL );
289
290         /* Destroy receive descriptor ring */
291         intel_destroy_ring ( intel, &intel->rx );
292
293         /* Discard any unused receive buffers */
294         intel_empty_rx ( intel );
295
296         /* Destroy transmit descriptor ring */
297         intel_destroy_ring ( intel, &intel->tx );
298
299         /* Reset the NIC, to flush the transmit and receive FIFOs */
300         intelx_reset ( intel );
301 }
302
303 /**
304  * Poll for completed and received packets
305  *
306  * @v netdev            Network device
307  */
308 static void intelx_poll ( struct net_device *netdev ) {
309         struct intel_nic *intel = netdev->priv;
310         uint32_t eicr;
311
312         /* Check for and acknowledge interrupts */
313         eicr = readl ( intel->regs + INTELX_EICR );
314         if ( ! eicr )
315                 return;
316
317         /* Poll for TX completions, if applicable */
318         if ( eicr & INTELX_EIRQ_TX0 )
319                 intel_poll_tx ( netdev );
320
321         /* Poll for RX completions, if applicable */
322         if ( eicr & ( INTELX_EIRQ_RX0 | INTELX_EIRQ_RXO ) )
323                 intel_poll_rx ( netdev );
324
325         /* Report receive overruns */
326         if ( eicr & INTELX_EIRQ_RXO )
327                 netdev_rx_err ( netdev, NULL, -ENOBUFS );
328
329         /* Check link state, if applicable */
330         if ( eicr & INTELX_EIRQ_LSC )
331                 intelx_check_link ( netdev );
332
333         /* Refill RX ring */
334         intel_refill_rx ( intel );
335 }
336
337 /**
338  * Enable or disable interrupts
339  *
340  * @v netdev            Network device
341  * @v enable            Interrupts should be enabled
342  */
343 static void intelx_irq ( struct net_device *netdev, int enable ) {
344         struct intel_nic *intel = netdev->priv;
345         uint32_t mask;
346
347         mask = ( INTELX_EIRQ_LSC | INTELX_EIRQ_RXO | INTELX_EIRQ_TX0 |
348                  INTELX_EIRQ_RX0 );
349         if ( enable ) {
350                 writel ( mask, intel->regs + INTELX_EIMS );
351         } else {
352                 writel ( mask, intel->regs + INTELX_EIMC );
353         }
354 }
355
356 /** Network device operations */
357 static struct net_device_operations intelx_operations = {
358         .open           = intelx_open,
359         .close          = intelx_close,
360         .transmit       = intel_transmit,
361         .poll           = intelx_poll,
362         .irq            = intelx_irq,
363 };
364
365 /******************************************************************************
366  *
367  * PCI interface
368  *
369  ******************************************************************************
370  */
371
372 /**
373  * Probe PCI device
374  *
375  * @v pci               PCI device
376  * @ret rc              Return status code
377  */
378 static int intelx_probe ( struct pci_device *pci ) {
379         struct net_device *netdev;
380         struct intel_nic *intel;
381         int rc;
382
383         /* Allocate and initialise net device */
384         netdev = alloc_etherdev ( sizeof ( *intel ) );
385         if ( ! netdev ) {
386                 rc = -ENOMEM;
387                 goto err_alloc;
388         }
389         netdev_init ( netdev, &intelx_operations );
390         intel = netdev->priv;
391         pci_set_drvdata ( pci, netdev );
392         netdev->dev = &pci->dev;
393         memset ( intel, 0, sizeof ( *intel ) );
394         intel->port = PCI_FUNC ( pci->busdevfn );
395         intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD );
396         intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD );
397
398         /* Fix up PCI device */
399         adjust_pci_device ( pci );
400
401         /* Map registers */
402         intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE );
403         if ( ! intel->regs ) {
404                 rc = -ENODEV;
405                 goto err_ioremap;
406         }
407
408         /* Reset the NIC */
409         if ( ( rc = intelx_reset ( intel ) ) != 0 )
410                 goto err_reset;
411
412         /* Fetch MAC address */
413         if ( ( rc = intelx_fetch_mac ( intel, netdev->hw_addr ) ) != 0 )
414                 goto err_fetch_mac;
415
416         /* Register network device */
417         if ( ( rc = register_netdev ( netdev ) ) != 0 )
418                 goto err_register_netdev;
419
420         /* Set initial link state */
421         intelx_check_link ( netdev );
422
423         return 0;
424
425         unregister_netdev ( netdev );
426  err_register_netdev:
427  err_fetch_mac:
428         intelx_reset ( intel );
429  err_reset:
430         iounmap ( intel->regs );
431  err_ioremap:
432         netdev_nullify ( netdev );
433         netdev_put ( netdev );
434  err_alloc:
435         return rc;
436 }
437
438 /**
439  * Remove PCI device
440  *
441  * @v pci               PCI device
442  */
443 static void intelx_remove ( struct pci_device *pci ) {
444         struct net_device *netdev = pci_get_drvdata ( pci );
445         struct intel_nic *intel = netdev->priv;
446
447         /* Unregister network device */
448         unregister_netdev ( netdev );
449
450         /* Reset the NIC */
451         intelx_reset ( intel );
452
453         /* Free network device */
454         iounmap ( intel->regs );
455         netdev_nullify ( netdev );
456         netdev_put ( netdev );
457 }
458
459 /** PCI device IDs */
460 static struct pci_device_id intelx_nics[] = {
461         PCI_ROM ( 0x8086, 0x10fb, "82599", "82599", 0 ),
462         PCI_ROM ( 0x8086, 0x1528, "x540at2", "X540-AT2", 0 ),
463         PCI_ROM ( 0x8086, 0x154d, "x520", "X520", 0 ),
464         PCI_ROM ( 0x8086, 0x1557, "82599", "82599", 0 ),
465 };
466
467 /** PCI driver */
468 struct pci_driver intelx_driver __pci_driver = {
469         .ids = intelx_nics,
470         .id_count = ( sizeof ( intelx_nics ) / sizeof ( intelx_nics[0] ) ),
471         .probe = intelx_probe,
472         .remove = intelx_remove,
473 };