2
* Copyright (C) 2012 Adrian Jamróz <adrian.jamroz@gmail.com>
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.
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.
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
20
FILE_LICENCE ( GPL2_OR_LATER );
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>
36
#define velocity_setbit(_reg, _mask) writeb ( readb ( _reg ) | _mask, _reg )
37
#define virt_to_le32bus(x) ( cpu_to_le32 ( virt_to_bus ( x ) ) )
41
* VIA Velocity network driver
45
/******************************************************************************
49
******************************************************************************
53
* Stop MII auto-polling
55
* @v vlc Velocity device
56
* @ret rc Return status code
58
static int velocity_autopoll_stop ( struct velocity_nic *vlc ) {
59
int timeout = VELOCITY_TIMEOUT_US;
61
/* Disable MII auto polling */
62
writeb ( 0, vlc->regs + VELOCITY_MIICR );
64
/* Wait for disabling to take effect */
67
if ( readb ( vlc->regs + VELOCITY_MIISR ) &
72
DBGC ( vlc, "MII autopoll stop timeout\n" );
77
* Start MII auto-polling
79
* @v vlc Velocity device
80
* @ret rc Return status code
82
static int velocity_autopoll_start ( struct velocity_nic *vlc ) {
83
int timeout = VELOCITY_TIMEOUT_US;
85
/* Enable MII auto polling */
86
writeb ( VELOCITY_MIICR_MAUTO, vlc->regs + VELOCITY_MIICR );
88
/* Wait for enabling to take effect */
91
if ( ( readb ( vlc->regs + VELOCITY_MIISR ) &
92
VELOCITY_MIISR_IDLE ) == 0 )
96
DBGC ( vlc, "MII autopoll start timeout\n" );
101
* Read from MII register
103
* @v mii MII interface
104
* @v reg Register address
105
* @ret value Data read, or negative error
107
static int velocity_mii_read ( struct mii_interface *mii, unsigned int reg ) {
108
struct velocity_nic *vlc =
109
container_of ( mii, struct velocity_nic, mii );
110
int timeout = VELOCITY_TIMEOUT_US;
113
DBGC2 ( vlc, "VELOCITY %p MII read reg %d\n", vlc, reg );
115
/* Disable autopolling before we can access MII */
116
velocity_autopoll_stop ( vlc );
118
/* Send read command and address */
119
writeb ( reg, vlc->regs + VELOCITY_MIIADDR );
120
velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_RCMD );
122
/* Wait for read to complete */
123
while ( timeout-- ) {
125
if ( ( readb ( vlc->regs + VELOCITY_MIICR ) &
126
VELOCITY_MIICR_RCMD ) == 0 ) {
127
result = readw ( vlc->regs + VELOCITY_MIIDATA );
128
velocity_autopoll_start ( vlc );
133
/* Restart autopolling */
134
velocity_autopoll_start ( vlc );
136
DBGC ( vlc, "MII read timeout\n" );
141
* Write to MII register
143
* @v mii MII interface
144
* @v reg Register address
145
* @v data Data to write
146
* @ret rc Return status code
148
static int velocity_mii_write ( struct mii_interface *mii, unsigned int reg,
150
struct velocity_nic *vlc =
151
container_of ( mii, struct velocity_nic, mii );
152
int timeout = VELOCITY_TIMEOUT_US;
154
DBGC2 ( vlc, "VELOCITY %p MII write reg %d data 0x%04x\n",
157
/* Disable autopolling before we can access MII */
158
velocity_autopoll_stop ( vlc );
160
/* Send write command, data and destination register */
161
writeb ( reg, vlc->regs + VELOCITY_MIIADDR );
162
writew ( data, vlc->regs + VELOCITY_MIIDATA );
163
velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_WCMD );
165
/* Wait for write to complete */
166
while ( timeout-- ) {
168
if ( ( readb ( vlc->regs + VELOCITY_MIICR ) &
169
VELOCITY_MIICR_WCMD ) == 0 ) {
170
velocity_autopoll_start ( vlc );
175
/* Restart autopolling */
176
velocity_autopoll_start ( vlc );
178
DBGC ( vlc, "MII write timeout\n" );
182
/** Velocity MII operations */
183
static struct mii_operations velocity_mii_operations = {
184
.read = velocity_mii_read,
185
.write = velocity_mii_write,
191
* @v vlc Velocity device
193
static void velocity_set_link ( struct velocity_nic *vlc ) {
196
/* Advertise 1000MBit */
197
tmp = velocity_mii_read ( &vlc->mii, MII_CTRL1000 );
198
tmp |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
199
velocity_mii_write ( &vlc->mii, MII_CTRL1000, tmp );
201
/* Enable GBit operation in MII Control Register */
202
tmp = velocity_mii_read ( &vlc->mii, MII_BMCR );
203
tmp |= BMCR_SPEED1000;
204
velocity_mii_write ( &vlc->mii, MII_BMCR, tmp );
207
/******************************************************************************
211
******************************************************************************
215
* Reload eeprom contents
217
* @v vlc Velocity device
219
static int velocity_reload_eeprom ( struct velocity_nic *vlc ) {
220
int timeout = VELOCITY_TIMEOUT_US;
222
/* Initiate reload */
223
velocity_setbit ( vlc->regs + VELOCITY_EECSR, VELOCITY_EECSR_RELOAD );
225
/* Wait for reload to complete */
226
while ( timeout-- ) {
228
if ( ( readb ( vlc->regs + VELOCITY_EECSR ) &
229
VELOCITY_EECSR_RELOAD ) == 0 )
233
DBGC ( vlc, "VELOCITY %p EEPROM reload timeout\n", vlc );
240
* @v vlc Velocity device
241
* @ret rc Return status code
243
static int velocity_reset ( struct velocity_nic *vlc ) {
244
int timeout = VELOCITY_TIMEOUT_US;
247
DBGC ( vlc, "VELOCITY %p reset\n", vlc );
249
/* clear sticky Power state bits */
250
tmp = readb ( vlc->regs + VELOCITY_STICKY );
251
tmp &= ~( VELOCITY_STICKY_DS0 | VELOCITY_STICKY_DS1 );
252
writeb ( tmp, vlc->regs + VELOCITY_STICKY );
254
/* clear PACPI, which might have been enabled by the EEPROM reload */
255
tmp = readb ( vlc->regs + VELOCITY_CFGA );
256
tmp &= ~VELOCITY_CFGA_PACPI;
257
writeb ( tmp, vlc->regs + VELOCITY_CFGA );
259
velocity_setbit ( vlc->regs + VELOCITY_CRS1, VELOCITY_CR1_SFRST );
261
/* Wait for reset to complete */
262
while ( timeout-- ) {
264
if ( ( readb ( vlc->regs + VELOCITY_CRS1 ) &
265
VELOCITY_CR1_SFRST ) == 0 )
272
/******************************************************************************
276
******************************************************************************
282
* @v netdev Network device
284
static void velocity_check_link ( struct net_device *netdev ) {
285
struct velocity_nic *vlc = netdev->priv;
287
if ( readb ( vlc->regs + VELOCITY_PHYSTS0 ) & VELOCITY_PHYSTS0_LINK ) {
288
netdev_link_up ( netdev );
289
DBGC ( vlc, "VELOCITY %p link up\n", vlc );
291
netdev_link_down ( netdev );
292
DBGC ( vlc, "VELOCITY %p link down\n", vlc );
295
/* The card disables auto-poll after a link change */
296
velocity_autopoll_start ( vlc );
299
/******************************************************************************
301
* Network device interface
303
******************************************************************************
307
* Allocate descriptor rings
309
* @v vlc Velocity device
310
* @ret rc Return status code
312
static int velocity_alloc_rings ( struct velocity_nic *vlc ) {
315
/* Allocate RX descriptor ring */
319
vlc->rx_ring = malloc_dma ( VELOCITY_RXDESC_SIZE, VELOCITY_RING_ALIGN );
320
if ( ! vlc->rx_ring )
323
memset ( vlc->rx_ring, 0, VELOCITY_RXDESC_SIZE );
325
DBGC2 ( vlc, "VELOCITY %p RX ring start address: %p(phys: %#08lx)\n",
326
vlc, vlc->rx_ring, virt_to_bus ( vlc->rx_ring ) );
328
/* Allocate TX descriptor ring */
331
vlc->tx_ring = malloc_dma ( VELOCITY_TXDESC_SIZE, VELOCITY_RING_ALIGN );
332
if ( ! vlc->tx_ring ) {
337
memset ( vlc->tx_ring, 0, VELOCITY_TXDESC_SIZE );
339
/* Send RX ring to the card */
340
writel ( virt_to_bus ( vlc->rx_ring ),
341
vlc->regs + VELOCITY_RXDESC_ADDR_LO );
342
writew ( VELOCITY_RXDESC_NUM - 1, vlc->regs + VELOCITY_RXDESCNUM );
344
/* Send TX ring to the card */
345
writel ( virt_to_bus ( vlc->tx_ring ),
346
vlc->regs + VELOCITY_TXDESC_ADDR_LO0 );
347
writew ( VELOCITY_TXDESC_NUM - 1, vlc->regs + VELOCITY_TXDESCNUM );
349
DBGC2 ( vlc, "VELOCITY %p TX ring start address: %p(phys: %#08lx)\n",
350
vlc, vlc->tx_ring, virt_to_bus ( vlc->tx_ring ) );
355
free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE );
360
* Refill receive descriptor ring
362
* @v vlc Velocity device
364
static void velocity_refill_rx ( struct velocity_nic *vlc ) {
365
struct velocity_rx_descriptor *desc;
366
struct io_buffer *iobuf;
369
/* Check for new packets */
370
while ( ( vlc->rx_prod - vlc->rx_cons ) < VELOCITY_RXDESC_NUM ) {
371
iobuf = alloc_iob ( VELOCITY_RX_MAX_LEN );
373
/* Memory pressure: try again next poll */
377
rx_idx = ( vlc->rx_prod++ % VELOCITY_RXDESC_NUM );
378
desc = &vlc->rx_ring[rx_idx];
380
/* Set descrptor fields */
382
desc->addr = virt_to_le32bus ( iobuf-> data );
383
desc->des2 = cpu_to_le32 (
384
VELOCITY_DES2_SIZE ( VELOCITY_RX_MAX_LEN - 1 ) |
387
vlc->rx_buffs[rx_idx] = iobuf;
390
/* Return RX descriptors in blocks of 4 (hw requirement) */
391
if ( rx_idx % 4 == 3 ) {
393
for (j = 0; j < 4; j++) {
394
desc = &vlc->rx_ring[rx_idx - j];
395
desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN );
403
if ( vlc->rx_commit ) {
404
writew ( vlc->rx_commit,
405
vlc->regs + VELOCITY_RXDESC_RESIDUECNT );
410
DBGC2 ( vlc, "VELOCITY %p refilled %d RX descriptors\n",
415
* Open network device
417
* @v netdev Network device
418
* @ret rc Return status code
420
static int velocity_open ( struct net_device *netdev ) {
421
struct velocity_nic *vlc = netdev->priv;
424
DBGC ( vlc, "VELOCITY %p open\n", vlc );
425
DBGC ( vlc, "VELOCITY %p regs at: %p\n", vlc, vlc->regs );
427
/* Allocate descriptor rings */
428
if ( ( rc = velocity_alloc_rings ( vlc ) ) != 0 )
431
velocity_refill_rx ( vlc );
433
/* Enable TX/RX queue */
434
writew ( VELOCITY_TXQCSRS_RUN0, vlc->regs + VELOCITY_TXQCSRS );
435
writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK,
436
vlc->regs + VELOCITY_RXQCSRS );
438
/* Enable interrupts */
439
writeb ( 0xff, vlc->regs + VELOCITY_IMR0 );
440
writeb ( 0xff, vlc->regs + VELOCITY_IMR1 );
443
writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRC0 );
444
writeb ( VELOCITY_CR1_DPOLL, vlc->regs + VELOCITY_CRC0 );
445
writeb ( VELOCITY_CR0_START | VELOCITY_CR0_TXON | VELOCITY_CR0_RXON,
446
vlc->regs + VELOCITY_CRS0 );
448
/* Receive all packets */
449
writeb ( 0xff, vlc->regs + VELOCITY_RCR );
451
/* Set initial link state */
452
velocity_check_link ( netdev );
454
velocity_autopoll_start ( vlc );
456
DBGC2 ( vlc, "VELOCITY %p CR3 %02x\n",
457
vlc, readb ( vlc->regs + 0x0B ) );
463
* Close network device
465
* @v netdev Network device
467
static void velocity_close ( struct net_device *netdev ) {
468
struct velocity_nic *vlc = netdev->priv;
472
writeb ( VELOCITY_CR0_TXON | VELOCITY_CR0_RXON,
473
vlc->regs + VELOCITY_CRC0 );
474
writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRS0 );
476
/* Clear RX ring information */
477
writel ( 0, vlc->regs + VELOCITY_RXDESC_ADDR_LO );
478
writew ( 0, vlc->regs + VELOCITY_RXDESCNUM );
480
/* Destroy RX ring */
481
free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE );
486
/* Discard receive buffers */
487
for ( i = 0 ; i < VELOCITY_RXDESC_NUM ; i++ ) {
488
if ( vlc->rx_buffs[i] )
489
free_iob ( vlc->rx_buffs[i] );
490
vlc->rx_buffs[i] = NULL;
493
/* Clear TX ring information */
494
writel ( 0, vlc->regs + VELOCITY_TXDESC_ADDR_LO0 );
495
writew ( 0, vlc->regs + VELOCITY_TXDESCNUM );
497
/* Destroy TX ring */
498
free_dma ( vlc->tx_ring, VELOCITY_TXDESC_SIZE );
507
* @v netdev Network device
508
* @v iobuf I/O buffer
509
* @ret rc Return status code
511
static int velocity_transmit ( struct net_device *netdev,
512
struct io_buffer *iobuf ) {
513
struct velocity_nic *vlc = netdev->priv;
514
struct velocity_tx_descriptor *desc;
517
/* Pad packet to minimum length */
518
iob_pad ( iobuf, ETH_ZLEN );
520
tx_idx = ( vlc->tx_prod++ % VELOCITY_TXDESC_NUM );
521
desc = &vlc->tx_ring[tx_idx];
523
/* Set packet size and transfer ownership to NIC */
524
desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN |
525
VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) );
526
/* Data in first desc fragment, only desc for packet, generate INT */
527
desc->des1 = cpu_to_le32 ( VELOCITY_DES1_FRAG ( 1 ) |
528
VELOCITY_DES1_TCPLS |
529
VELOCITY_DES1_INTR );
531
desc->frags[0].addr = virt_to_le32bus ( iobuf->data );
532
desc->frags[0].des2 = cpu_to_le32 (
533
VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) );
538
velocity_setbit ( vlc->regs + VELOCITY_TXQCSRS, VELOCITY_TXQCSRS_WAK0 );
540
DBGC2 ( vlc, "VELOCITY %p tx_prod=%d desc=%p iobuf=%p len=%zd\n",
541
vlc, tx_idx, desc, iobuf->data, iob_len ( iobuf ) );
547
* Poll for received packets.
549
* @v vlc Velocity device
551
static void velocity_poll_rx ( struct velocity_nic *vlc ) {
552
struct velocity_rx_descriptor *desc;
553
struct io_buffer *iobuf;
558
/* Check for packets */
559
while ( vlc->rx_cons != vlc->rx_prod ) {
560
rx_idx = ( vlc->rx_cons % VELOCITY_RXDESC_NUM );
561
desc = &vlc->rx_ring[rx_idx];
563
des0 = cpu_to_le32 ( desc->des0 );
565
/* Return if descriptor still in use */
566
if ( des0 & VELOCITY_DES0_OWN )
569
iobuf = vlc->rx_buffs[rx_idx];
571
/* Get length, strip CRC */
572
len = VELOCITY_DES0_RMBC ( des0 ) - 4;
573
iob_put ( iobuf, len );
575
DBGC2 ( vlc, "VELOCITY %p got packet on idx=%d (prod=%d), len %zd\n",
576
vlc, rx_idx, vlc->rx_prod % VELOCITY_RXDESC_NUM, len );
578
if ( des0 & VELOCITY_DES0_RX_ERR ) {
579
/* Report receive error */
580
netdev_rx_err ( vlc->netdev, iobuf, -EINVAL );
581
DBGC ( vlc, "VELOCITY %p receive error, status: %02x\n",
583
} else if ( des0 & VELOCITY_DES0_RXOK ) {
584
/* Report receive success */
585
netdev_rx( vlc->netdev, iobuf );
587
/* Card indicated neither success nor failure
588
* Technically this shouldn't happen, but we saw it
589
* in debugging once. */
590
DBGC ( vlc, "VELOCITY %p RX neither ERR nor OK: %04x\n",
592
DBGC ( vlc, "packet len: %zd\n", len );
593
DBGC_HD ( vlc, iobuf->data, 64 );
595
/* we don't know what it is, treat is as an error */
596
netdev_rx_err ( vlc->netdev, iobuf, -EINVAL );
604
* Poll for completed packets.
606
* @v vlc Velocity device
608
static void velocity_poll_tx ( struct velocity_nic *vlc ) {
609
struct velocity_tx_descriptor *desc;
612
/* Check for packets */
613
while ( vlc->tx_cons != vlc->tx_prod ) {
614
tx_idx = ( vlc->tx_cons % VELOCITY_TXDESC_NUM );
615
desc = &vlc->tx_ring[tx_idx];
617
/* Return if descriptor still in use */
618
if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_OWN )
622
if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_TERR ) {
623
netdev_tx_complete_next_err ( vlc->netdev, -EINVAL );
627
netdev_tx_complete_next ( vlc->netdev );
629
DBGC2 ( vlc, "VELOCITY %p poll_tx cons=%d prod=%d tsr=%04x\n",
630
vlc, tx_idx, vlc->tx_prod % VELOCITY_TXDESC_NUM,
631
( desc->des0 & 0xffff ) );
637
* Poll for completed and received packets
639
* @v netdev Network device
641
static void velocity_poll ( struct net_device *netdev ) {
642
struct velocity_nic *vlc = netdev->priv;
645
isr1 = readb ( vlc->regs + VELOCITY_ISR1 );
648
writew ( 0xFFFF, vlc->regs + VELOCITY_ISR0 );
650
/* Check for competed packets */
651
velocity_poll_rx ( vlc );
652
velocity_poll_tx ( vlc );
654
if ( isr1 & VELOCITY_ISR1_SRCI ) {
655
/* Update linkstate */
656
DBGC2 ( vlc, "VELOCITY %p link status interrupt\n", vlc );
657
velocity_check_link ( netdev );
660
velocity_refill_rx ( vlc );
662
/* deal with potential RX stall caused by RX ring underrun */
663
writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK,
664
vlc->regs + VELOCITY_RXQCSRS );
668
* Enable or disable interrupts
670
* @v netdev Network device
671
* @v enable Interrupts should be enabled
673
static void velocity_irq ( struct net_device *netdev, int enable ) {
674
struct velocity_nic *vlc = netdev->priv;
676
DBGC ( vlc, "VELOCITY %p interrupts %s\n", vlc,
677
enable ? "enable" : "disable" );
680
/* Enable interrupts */
681
writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRS3 );
683
/* Disable interrupts */
684
writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRC3 );
688
/** Velocity network device operations */
689
static struct net_device_operations velocity_operations = {
690
.open = velocity_open,
691
.close = velocity_close,
692
.transmit = velocity_transmit,
693
.poll = velocity_poll,
697
/******************************************************************************
701
******************************************************************************
708
* @ret rc Return status code
710
static int velocity_probe ( struct pci_device *pci ) {
711
struct net_device *netdev;
712
struct velocity_nic *vlc;
715
/* Allocate and initialise net device */
716
netdev = alloc_etherdev ( sizeof ( *vlc ) );
721
netdev_init ( netdev, &velocity_operations );
723
pci_set_drvdata ( pci, netdev );
724
netdev->dev = &pci->dev;
726
/* Fix up PCI device */
727
adjust_pci_device ( pci );
730
vlc->regs = ioremap ( pci->membase, VELOCITY_BAR_SIZE );
731
vlc->netdev = netdev;
734
if ( ( rc = velocity_reset ( vlc ) ) != 0 )
738
if ( ( rc = velocity_reload_eeprom ( vlc ) ) != 0 )
741
/* Get MAC address */
742
netdev->hw_addr[0] = readb ( vlc->regs + VELOCITY_MAC0 );
743
netdev->hw_addr[1] = readb ( vlc->regs + VELOCITY_MAC1 );
744
netdev->hw_addr[2] = readb ( vlc->regs + VELOCITY_MAC2 );
745
netdev->hw_addr[3] = readb ( vlc->regs + VELOCITY_MAC3 );
746
netdev->hw_addr[4] = readb ( vlc->regs + VELOCITY_MAC4 );
747
netdev->hw_addr[5] = readb ( vlc->regs + VELOCITY_MAC5 );
749
/* Initialise and reset MII interface */
750
mii_init ( &vlc->mii, &velocity_mii_operations );
751
if ( ( rc = mii_reset ( &vlc->mii ) ) != 0 ) {
752
DBGC ( vlc, "VELOCITY %p could not reset MII: %s\n",
753
vlc, strerror ( rc ) );
757
/* Enable proper link advertising */
758
velocity_set_link ( vlc );
760
/* Register network device */
761
if ( ( rc = register_netdev ( netdev ) ) != 0 )
762
goto err_register_netdev;
768
velocity_reset ( vlc );
770
netdev_nullify ( netdev );
771
netdev_put ( netdev );
781
static void velocity_remove ( struct pci_device *pci ) {
782
struct net_device *netdev = pci_get_drvdata ( pci );
783
struct velocity_nic *vlc = netdev->priv;
785
/* Unregister network device */
786
unregister_netdev ( netdev );
789
velocity_reset ( vlc );
791
/* Free network device */
792
netdev_nullify ( netdev );
793
netdev_put ( netdev );
796
/** Velocity PCI device IDs */
797
static struct pci_device_id velocity_nics[] = {
798
PCI_ROM ( 0x1106, 0x3119, "vt6122", "VIA Velocity", 0 ),
801
/** Velocity PCI driver */
802
struct pci_driver velocity_driver __pci_driver = {
803
.ids = velocity_nics,
804
.id_count = ( sizeof ( velocity_nics ) / sizeof ( velocity_nics[0] ) ),
805
.probe = velocity_probe,
806
.remove = velocity_remove,