iPXE
intelxl.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2018 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdint.h>
00027 #include <string.h>
00028 #include <stdio.h>
00029 #include <unistd.h>
00030 #include <errno.h>
00031 #include <byteswap.h>
00032 #include <ipxe/netdevice.h>
00033 #include <ipxe/ethernet.h>
00034 #include <ipxe/if_ether.h>
00035 #include <ipxe/iobuf.h>
00036 #include <ipxe/malloc.h>
00037 #include <ipxe/pci.h>
00038 #include <ipxe/version.h>
00039 #include "intelxl.h"
00040 
00041 /** @file
00042  *
00043  * Intel 40 Gigabit Ethernet network card driver
00044  *
00045  */
00046 
00047 /******************************************************************************
00048  *
00049  * Device reset
00050  *
00051  ******************************************************************************
00052  */
00053 
00054 /**
00055  * Reset hardware
00056  *
00057  * @v intelxl           Intel device
00058  * @ret rc              Return status code
00059  */
00060 static int intelxl_reset ( struct intelxl_nic *intelxl ) {
00061         uint32_t pfgen_ctrl;
00062 
00063         /* Perform a global software reset */
00064         pfgen_ctrl = readl ( intelxl->regs + INTELXL_PFGEN_CTRL );
00065         writel ( ( pfgen_ctrl | INTELXL_PFGEN_CTRL_PFSWR ),
00066                  intelxl->regs + INTELXL_PFGEN_CTRL );
00067         mdelay ( INTELXL_RESET_DELAY_MS );
00068 
00069         return 0;
00070 }
00071 
00072 /******************************************************************************
00073  *
00074  * MAC address
00075  *
00076  ******************************************************************************
00077  */
00078 
00079 /**
00080  * Fetch initial MAC address and maximum frame size
00081  *
00082  * @v intelxl           Intel device
00083  * @v netdev            Network device
00084  * @ret rc              Return status code
00085  */
00086 static int intelxl_fetch_mac ( struct intelxl_nic *intelxl,
00087                                struct net_device *netdev ) {
00088         union intelxl_receive_address mac;
00089         uint32_t prtgl_sal;
00090         uint32_t prtgl_sah;
00091         size_t mfs;
00092 
00093         /* Read NVM-loaded address */
00094         prtgl_sal = readl ( intelxl->regs + INTELXL_PRTGL_SAL );
00095         prtgl_sah = readl ( intelxl->regs + INTELXL_PRTGL_SAH );
00096         mac.reg.low = cpu_to_le32 ( prtgl_sal );
00097         mac.reg.high = cpu_to_le32 ( prtgl_sah );
00098 
00099         /* Check that address is valid */
00100         if ( ! is_valid_ether_addr ( mac.raw ) ) {
00101                 DBGC ( intelxl, "INTELXL %p has invalid MAC address (%s)\n",
00102                        intelxl, eth_ntoa ( mac.raw ) );
00103                 return -ENOENT;
00104         }
00105 
00106         /* Copy MAC address */
00107         DBGC ( intelxl, "INTELXL %p has autoloaded MAC address %s\n",
00108                intelxl, eth_ntoa ( mac.raw ) );
00109         memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN );
00110 
00111         /* Get maximum frame size */
00112         mfs = INTELXL_PRTGL_SAH_MFS_GET ( prtgl_sah );
00113         netdev->max_pkt_len = ( mfs - 4 /* CRC */ );
00114 
00115         return 0;
00116 }
00117 
00118 /******************************************************************************
00119  *
00120  * Admin queue
00121  *
00122  ******************************************************************************
00123  */
00124 
00125 /**
00126  * Create admin queue
00127  *
00128  * @v intelxl           Intel device
00129  * @v admin             Admin queue
00130  * @ret rc              Return status code
00131  */
00132 static int intelxl_create_admin ( struct intelxl_nic *intelxl,
00133                                   struct intelxl_admin *admin ) {
00134         size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
00135         void *admin_regs = ( intelxl->regs + admin->reg );
00136         physaddr_t address;
00137 
00138         /* Allocate admin queue */
00139         admin->desc = malloc_dma ( ( len + sizeof ( *admin->buffer ) ),
00140                                    INTELXL_ALIGN );
00141         if ( ! admin->desc )
00142                 return -ENOMEM;
00143         admin->buffer = ( ( ( void * ) admin->desc ) + len );
00144 
00145         /* Initialise admin queue */
00146         memset ( admin->desc, 0, len );
00147 
00148         /* Reset head and tail registers */
00149         writel ( 0, admin_regs + INTELXL_ADMIN_HEAD );
00150         writel ( 0, admin_regs + INTELXL_ADMIN_TAIL );
00151 
00152         /* Reset queue index */
00153         admin->index = 0;
00154 
00155         /* Program queue address */
00156         address = virt_to_bus ( admin->desc );
00157         writel ( ( address & 0xffffffffUL ), admin_regs + INTELXL_ADMIN_BAL );
00158         if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
00159                 writel ( ( ( ( uint64_t ) address ) >> 32 ),
00160                          admin_regs + INTELXL_ADMIN_BAH );
00161         } else {
00162                 writel ( 0, admin_regs + INTELXL_ADMIN_BAH );
00163         }
00164 
00165         /* Program queue length and enable queue */
00166         writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
00167                    INTELXL_ADMIN_LEN_ENABLE ),
00168                  admin_regs + INTELXL_ADMIN_LEN );
00169 
00170         DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
00171                "[%08llx,%08llx)\n", intelxl,
00172                ( ( admin->reg == INTELXL_ADMIN_CMD ) ? 'T' : 'R' ),
00173                ( ( unsigned long long ) address ),
00174                ( ( unsigned long long ) address + len ),
00175                ( ( unsigned long long ) virt_to_bus ( admin->buffer ) ),
00176                ( ( unsigned long long ) ( virt_to_bus ( admin->buffer ) +
00177                                           sizeof ( admin->buffer[0] ) ) ) );
00178         return 0;
00179 }
00180 
00181 /**
00182  * Destroy admin queue
00183  *
00184  * @v intelxl           Intel device
00185  * @v admin             Admin queue
00186  */
00187 static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
00188                                     struct intelxl_admin *admin ) {
00189         size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
00190         void *admin_regs = ( intelxl->regs + admin->reg );
00191 
00192         /* Disable queue */
00193         writel ( 0, admin_regs + INTELXL_ADMIN_LEN );
00194 
00195         /* Free queue */
00196         free_dma ( admin->desc, ( len + sizeof ( *admin->buffer ) ) );
00197 }
00198 
00199 /**
00200  * Issue admin queue command
00201  *
00202  * @v intelxl           Intel device
00203  * @v cmd               Command descriptor
00204  * @ret rc              Return status code
00205  */
00206 static int intelxl_admin_command ( struct intelxl_nic *intelxl,
00207                                    struct intelxl_admin_descriptor *cmd ) {
00208         struct intelxl_admin *admin = &intelxl->command;
00209         void *admin_regs = ( intelxl->regs + admin->reg );
00210         struct intelxl_admin_descriptor *desc;
00211         uint64_t buffer;
00212         unsigned int index;
00213         unsigned int tail;
00214         unsigned int i;
00215         int rc;
00216 
00217         /* Get next queue entry */
00218         index = admin->index++;
00219         tail = ( admin->index % INTELXL_ADMIN_NUM_DESC );
00220         desc = &admin->desc[index % INTELXL_ADMIN_NUM_DESC];
00221 
00222         /* Clear must-be-zero flags */
00223         cmd->flags &= ~cpu_to_le16 ( INTELXL_ADMIN_FL_DD |
00224                                      INTELXL_ADMIN_FL_CMP |
00225                                      INTELXL_ADMIN_FL_ERR );
00226 
00227         /* Clear return value */
00228         cmd->ret = 0;
00229 
00230         /* Populate cookie */
00231         cmd->cookie = cpu_to_le32 ( index );
00232 
00233         /* Populate data buffer address if applicable */
00234         if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
00235                 buffer = virt_to_bus ( admin->buffer );
00236                 cmd->params.buffer.high = cpu_to_le32 ( buffer >> 32 );
00237                 cmd->params.buffer.low = cpu_to_le32 ( buffer & 0xffffffffUL );
00238         }
00239 
00240         /* Copy command descriptor to queue entry */
00241         memcpy ( desc, cmd, sizeof ( *desc ) );
00242         DBGC2 ( intelxl, "INTELXL %p admin command %#x:\n", intelxl, index );
00243         DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc, sizeof ( *desc ) );
00244 
00245         /* Post command descriptor */
00246         wmb();
00247         writel ( tail, admin_regs + INTELXL_ADMIN_TAIL );
00248 
00249         /* Wait for completion */
00250         for ( i = 0 ; i < INTELXL_ADMIN_MAX_WAIT_MS ; i++ ) {
00251 
00252                 /* If response is not complete, delay 1ms and retry */
00253                 if ( ! ( desc->flags & INTELXL_ADMIN_FL_DD ) ) {
00254                         mdelay ( 1 );
00255                         continue;
00256                 }
00257                 DBGC2 ( intelxl, "INTELXL %p admin command %#x response:\n",
00258                         intelxl, index );
00259                 DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc,
00260                             sizeof ( *desc ) );
00261 
00262                 /* Check for cookie mismatch */
00263                 if ( desc->cookie != cmd->cookie ) {
00264                         DBGC ( intelxl, "INTELXL %p admin command %#x bad "
00265                                "cookie %#x\n", intelxl, index,
00266                                le32_to_cpu ( desc->cookie ) );
00267                         rc = -EPROTO;
00268                         goto err;
00269                 }
00270 
00271                 /* Check for errors */
00272                 if ( desc->ret != 0 ) {
00273                         DBGC ( intelxl, "INTELXL %p admin command %#x error "
00274                                "%d\n", intelxl, index,
00275                                le16_to_cpu ( desc->ret ) );
00276                         rc = -EIO;
00277                         goto err;
00278                 }
00279 
00280                 /* Copy response back to command descriptor */
00281                 memcpy ( cmd, desc, sizeof ( *cmd ) );
00282 
00283                 /* Success */
00284                 return 0;
00285         }
00286 
00287         rc = -ETIMEDOUT;
00288         DBGC ( intelxl, "INTELXL %p timed out waiting for admin command %#x:\n",
00289                intelxl, index );
00290  err:
00291         DBGC_HDA ( intelxl, virt_to_phys ( desc ), cmd, sizeof ( *cmd ) );
00292         DBGC_HDA ( intelxl, virt_to_phys ( desc ), desc, sizeof ( *desc ) );
00293         return rc;
00294 }
00295 
00296 /**
00297  * Get firmware version
00298  *
00299  * @v intelxl           Intel device
00300  * @ret rc              Return status code
00301  */
00302 static int intelxl_admin_version ( struct intelxl_nic *intelxl ) {
00303         struct intelxl_admin_descriptor cmd;
00304         struct intelxl_admin_version_params *version = &cmd.params.version;
00305         unsigned int api;
00306         int rc;
00307 
00308         /* Populate descriptor */
00309         memset ( &cmd, 0, sizeof ( cmd ) );
00310         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_VERSION );
00311 
00312         /* Issue command */
00313         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00314                 return rc;
00315         api = le16_to_cpu ( version->api.major );
00316         DBGC ( intelxl, "INTELXL %p firmware v%d.%d API v%d.%d\n",
00317                intelxl, le16_to_cpu ( version->firmware.major ),
00318                le16_to_cpu ( version->firmware.minor ),
00319                api, le16_to_cpu ( version->api.minor ) );
00320 
00321         /* Check for API compatibility */
00322         if ( api > INTELXL_ADMIN_API_MAJOR ) {
00323                 DBGC ( intelxl, "INTELXL %p unsupported API v%d\n",
00324                        intelxl, api );
00325                 return -ENOTSUP;
00326         }
00327 
00328         return 0;
00329 }
00330 
00331 /**
00332  * Report driver version
00333  *
00334  * @v intelxl           Intel device
00335  * @ret rc              Return status code
00336  */
00337 static int intelxl_admin_driver ( struct intelxl_nic *intelxl ) {
00338         struct intelxl_admin_descriptor cmd;
00339         struct intelxl_admin_driver_params *driver = &cmd.params.driver;
00340         struct intelxl_admin_driver_buffer *buf =
00341                 &intelxl->command.buffer->driver;
00342         int rc;
00343 
00344         /* Populate descriptor */
00345         memset ( &cmd, 0, sizeof ( cmd ) );
00346         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_DRIVER );
00347         cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
00348         cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
00349         driver->major = product_major_version;
00350         driver->minor = product_minor_version;
00351         snprintf ( buf->name, sizeof ( buf->name ), "%s",
00352                    ( product_name[0] ? product_name : product_short_name ) );
00353 
00354         /* Issue command */
00355         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00356                 return rc;
00357 
00358         return 0;
00359 }
00360 
00361 /**
00362  * Shutdown admin queues
00363  *
00364  * @v intelxl           Intel device
00365  * @ret rc              Return status code
00366  */
00367 static int intelxl_admin_shutdown ( struct intelxl_nic *intelxl ) {
00368         struct intelxl_admin_descriptor cmd;
00369         struct intelxl_admin_shutdown_params *shutdown = &cmd.params.shutdown;
00370         int rc;
00371 
00372         /* Populate descriptor */
00373         memset ( &cmd, 0, sizeof ( cmd ) );
00374         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_SHUTDOWN );
00375         shutdown->unloading = INTELXL_ADMIN_SHUTDOWN_UNLOADING;
00376 
00377         /* Issue command */
00378         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00379                 return rc;
00380 
00381         return 0;
00382 }
00383 
00384 /**
00385  * Get switch configuration
00386  *
00387  * @v intelxl           Intel device
00388  * @ret rc              Return status code
00389  */
00390 static int intelxl_admin_switch ( struct intelxl_nic *intelxl ) {
00391         struct intelxl_admin_descriptor cmd;
00392         struct intelxl_admin_switch_params *sw = &cmd.params.sw;
00393         struct intelxl_admin_switch_buffer *buf = &intelxl->command.buffer->sw;
00394         struct intelxl_admin_switch_config *cfg = &buf->cfg;
00395         int rc;
00396 
00397         /* Populate descriptor */
00398         memset ( &cmd, 0, sizeof ( cmd ) );
00399         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_SWITCH );
00400         cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
00401         cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
00402 
00403         /* Get each configuration in turn */
00404         do {
00405                 /* Issue command */
00406                 if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00407                         return rc;
00408 
00409                 /* Dump raw configuration */
00410                 DBGC2 ( intelxl, "INTELXL %p SEID %#04x:\n",
00411                         intelxl, le16_to_cpu ( cfg->seid ) );
00412                 DBGC2_HDA ( intelxl, 0, cfg, sizeof ( *cfg ) );
00413 
00414                 /* Parse response */
00415                 if ( cfg->type == INTELXL_ADMIN_SWITCH_TYPE_VSI ) {
00416                         intelxl->vsi = le16_to_cpu ( cfg->seid );
00417                         DBGC ( intelxl, "INTELXL %p VSI %#04x uplink %#04x "
00418                                "downlink %#04x conn %#02x\n", intelxl,
00419                                intelxl->vsi, le16_to_cpu ( cfg->uplink ),
00420                                le16_to_cpu ( cfg->downlink ), cfg->connection );
00421                 }
00422 
00423         } while ( sw->next );
00424 
00425         /* Check that we found a VSI */
00426         if ( ! intelxl->vsi ) {
00427                 DBGC ( intelxl, "INTELXL %p has no VSI\n", intelxl );
00428                 return -ENOENT;
00429         }
00430 
00431         return 0;
00432 }
00433 
00434 /**
00435  * Get VSI parameters
00436  *
00437  * @v intelxl           Intel device
00438  * @ret rc              Return status code
00439  */
00440 static int intelxl_admin_vsi ( struct intelxl_nic *intelxl ) {
00441         struct intelxl_admin_descriptor cmd;
00442         struct intelxl_admin_vsi_params *vsi = &cmd.params.vsi;
00443         struct intelxl_admin_vsi_buffer *buf = &intelxl->command.buffer->vsi;
00444         int rc;
00445 
00446         /* Populate descriptor */
00447         memset ( &cmd, 0, sizeof ( cmd ) );
00448         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_VSI );
00449         cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
00450         cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
00451         vsi->vsi = cpu_to_le16 ( intelxl->vsi );
00452 
00453         /* Issue command */
00454         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00455                 return rc;
00456 
00457         /* Parse response */
00458         intelxl->queue = le16_to_cpu ( buf->queue[0] );
00459         intelxl->qset = le16_to_cpu ( buf->qset[0] );
00460         DBGC ( intelxl, "INTELXL %p VSI %#04x queue %#04x qset %#04x\n",
00461                intelxl, intelxl->vsi, intelxl->queue, intelxl->qset );
00462 
00463         return 0;
00464 }
00465 
00466 /**
00467  * Set VSI promiscuous modes
00468  *
00469  * @v intelxl           Intel device
00470  * @ret rc              Return status code
00471  */
00472 static int intelxl_admin_promisc ( struct intelxl_nic *intelxl ) {
00473         struct intelxl_admin_descriptor cmd;
00474         struct intelxl_admin_promisc_params *promisc = &cmd.params.promisc;
00475         uint16_t flags;
00476         int rc;
00477 
00478         /* Populate descriptor */
00479         memset ( &cmd, 0, sizeof ( cmd ) );
00480         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_PROMISC );
00481         flags = ( INTELXL_ADMIN_PROMISC_FL_UNICAST |
00482                   INTELXL_ADMIN_PROMISC_FL_MULTICAST |
00483                   INTELXL_ADMIN_PROMISC_FL_BROADCAST |
00484                   INTELXL_ADMIN_PROMISC_FL_VLAN );
00485         promisc->flags = cpu_to_le16 ( flags );
00486         promisc->valid = cpu_to_le16 ( flags );
00487         promisc->vsi = cpu_to_le16 ( intelxl->vsi );
00488 
00489         /* Issue command */
00490         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00491                 return rc;
00492 
00493         return 0;
00494 }
00495 
00496 /**
00497  * Restart autonegotiation
00498  *
00499  * @v intelxl           Intel device
00500  * @ret rc              Return status code
00501  */
00502 static int intelxl_admin_autoneg ( struct intelxl_nic *intelxl ) {
00503         struct intelxl_admin_descriptor cmd;
00504         struct intelxl_admin_autoneg_params *autoneg = &cmd.params.autoneg;
00505         int rc;
00506 
00507         /* Populate descriptor */
00508         memset ( &cmd, 0, sizeof ( cmd ) );
00509         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_AUTONEG );
00510         autoneg->flags = ( INTELXL_ADMIN_AUTONEG_FL_RESTART |
00511                            INTELXL_ADMIN_AUTONEG_FL_ENABLE );
00512 
00513         /* Issue command */
00514         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00515                 return rc;
00516 
00517         return 0;
00518 }
00519 
00520 /**
00521  * Get link status
00522  *
00523  * @v netdev            Network device
00524  * @ret rc              Return status code
00525  */
00526 static int intelxl_admin_link ( struct net_device *netdev ) {
00527         struct intelxl_nic *intelxl = netdev->priv;
00528         struct intelxl_admin_descriptor cmd;
00529         struct intelxl_admin_link_params *link = &cmd.params.link;
00530         int rc;
00531 
00532         /* Populate descriptor */
00533         memset ( &cmd, 0, sizeof ( cmd ) );
00534         cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_LINK );
00535         link->notify = INTELXL_ADMIN_LINK_NOTIFY;
00536 
00537         /* Issue command */
00538         if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
00539                 return rc;
00540         DBGC ( intelxl, "INTELXL %p PHY %#02x speed %#02x status %#02x\n",
00541                intelxl, link->phy, link->speed, link->status );
00542 
00543         /* Update network device */
00544         if ( link->status & INTELXL_ADMIN_LINK_UP ) {
00545                 netdev_link_up ( netdev );
00546         } else {
00547                 netdev_link_down ( netdev );
00548         }
00549 
00550         return 0;
00551 }
00552 
00553 /**
00554  * Refill admin event queue
00555  *
00556  * @v intelxl           Intel device
00557  */
00558 static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) {
00559         struct intelxl_admin *admin = &intelxl->event;
00560         void *admin_regs = ( intelxl->regs + admin->reg );
00561         unsigned int tail;
00562 
00563         /* Update tail pointer */
00564         tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) %
00565                  INTELXL_ADMIN_NUM_DESC );
00566         writel ( tail, admin_regs + INTELXL_ADMIN_TAIL );
00567 }
00568 
00569 /**
00570  * Poll admin event queue
00571  *
00572  * @v netdev            Network device
00573  */
00574 static void intelxl_poll_admin ( struct net_device *netdev ) {
00575         struct intelxl_nic *intelxl = netdev->priv;
00576         struct intelxl_admin *admin = &intelxl->event;
00577         struct intelxl_admin_descriptor *desc;
00578 
00579         /* Check for events */
00580         while ( 1 ) {
00581 
00582                 /* Get next event descriptor */
00583                 desc = &admin->desc[admin->index % INTELXL_ADMIN_NUM_DESC];
00584 
00585                 /* Stop if descriptor is not yet completed */
00586                 if ( ! ( desc->flags & INTELXL_ADMIN_FL_DD ) )
00587                         return;
00588                 DBGC2 ( intelxl, "INTELXL %p admin event %#x:\n",
00589                         intelxl, admin->index );
00590                 DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc,
00591                             sizeof ( *desc ) );
00592 
00593                 /* Handle event */
00594                 switch ( desc->opcode ) {
00595                 case cpu_to_le16 ( INTELXL_ADMIN_LINK ):
00596                         intelxl_admin_link ( netdev );
00597                         break;
00598                 default:
00599                         DBGC ( intelxl, "INTELXL %p admin event %#x "
00600                                "unrecognised opcode %#04x\n", intelxl,
00601                                admin->index, le16_to_cpu ( desc->opcode ) );
00602                         break;
00603                 }
00604 
00605                 /* Clear event completion flag */
00606                 desc->flags = 0;
00607                 wmb();
00608 
00609                 /* Update index and refill queue */
00610                 admin->index++;
00611                 intelxl_refill_admin ( intelxl );
00612         }
00613 }
00614 
00615 /**
00616  * Open admin queues
00617  *
00618  * @v intelxl           Intel device
00619  * @ret rc              Return status code
00620  */
00621 static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
00622         int rc;
00623 
00624         /* Create admin event queue */
00625         if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->event ) ) != 0 )
00626                 goto err_create_event;
00627 
00628         /* Create admin command queue */
00629         if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->command ) ) != 0 )
00630                 goto err_create_command;
00631 
00632         /* Post all descriptors to event queue */
00633         intelxl_refill_admin ( intelxl );
00634 
00635         /* Get firmware version */
00636         if ( ( rc = intelxl_admin_version ( intelxl ) ) != 0 )
00637                 goto err_version;
00638 
00639         /* Report driver version */
00640         if ( ( rc = intelxl_admin_driver ( intelxl ) ) != 0 )
00641                 goto err_driver;
00642 
00643         return 0;
00644 
00645  err_driver:
00646  err_version:
00647         intelxl_destroy_admin ( intelxl, &intelxl->command );
00648  err_create_command:
00649         intelxl_destroy_admin ( intelxl, &intelxl->event );
00650  err_create_event:
00651         return rc;
00652 }
00653 
00654 /**
00655  * Close admin queues
00656  *
00657  * @v intelxl           Intel device
00658  */
00659 static void intelxl_close_admin ( struct intelxl_nic *intelxl ) {
00660 
00661         /* Shut down admin queues */
00662         intelxl_admin_shutdown ( intelxl );
00663 
00664         /* Destroy admin command queue */
00665         intelxl_destroy_admin ( intelxl, &intelxl->command );
00666 
00667         /* Destroy admin event queue */
00668         intelxl_destroy_admin ( intelxl, &intelxl->event );
00669 }
00670 
00671 /******************************************************************************
00672  *
00673  * Descriptor rings
00674  *
00675  ******************************************************************************
00676  */
00677 
00678 /**
00679  * Dump queue context (for debugging)
00680  *
00681  * @v intelxl           Intel device
00682  * @v op                Context operation
00683  * @v len               Size of context
00684  */
00685 static __attribute__ (( unused )) void
00686 intelxl_context_dump ( struct intelxl_nic *intelxl, uint32_t op, size_t len ) {
00687         struct intelxl_context_line line;
00688         uint32_t pfcm_lanctxctl;
00689         uint32_t pfcm_lanctxstat;
00690         unsigned int queue;
00691         unsigned int index;
00692         unsigned int i;
00693 
00694         /* Do nothing unless debug output is enabled */
00695         if ( ! DBG_EXTRA )
00696                 return;
00697 
00698         /* Dump context */
00699         DBGC2 ( intelxl, "INTELXL %p context %#08x:\n", intelxl, op );
00700         for ( index = 0 ; ( sizeof ( line ) * index ) < len ; index++ ) {
00701 
00702                 /* Start context operation */
00703                 queue = ( intelxl->base + intelxl->queue );
00704                 pfcm_lanctxctl =
00705                         ( INTELXL_PFCM_LANCTXCTL_QUEUE_NUM ( queue ) |
00706                           INTELXL_PFCM_LANCTXCTL_SUB_LINE ( index ) |
00707                           INTELXL_PFCM_LANCTXCTL_OP_CODE_READ | op );
00708                 writel ( pfcm_lanctxctl,
00709                          intelxl->regs + INTELXL_PFCM_LANCTXCTL );
00710 
00711                 /* Wait for operation to complete */
00712                 for ( i = 0 ; i < INTELXL_CTX_MAX_WAIT_MS ; i++ ) {
00713 
00714                         /* Check if operation is complete */
00715                         pfcm_lanctxstat = readl ( intelxl->regs +
00716                                                   INTELXL_PFCM_LANCTXSTAT );
00717                         if ( pfcm_lanctxstat & INTELXL_PFCM_LANCTXSTAT_DONE )
00718                                 break;
00719 
00720                         /* Delay */
00721                         mdelay ( 1 );
00722                 }
00723 
00724                 /* Read context data */
00725                 for ( i = 0 ; i < ( sizeof ( line ) /
00726                                     sizeof ( line.raw[0] ) ) ; i++ ) {
00727                         line.raw[i] = readl ( intelxl->regs +
00728                                               INTELXL_PFCM_LANCTXDATA ( i ) );
00729                 }
00730                 DBGC2_HDA ( intelxl, ( sizeof ( line ) * index ),
00731                             &line, sizeof ( line ) );
00732         }
00733 }
00734 
00735 /**
00736  * Program queue context line
00737  *
00738  * @v intelxl           Intel device
00739  * @v line              Queue context line
00740  * @v index             Line number
00741  * @v op                Context operation
00742  * @ret rc              Return status code
00743  */
00744 static int intelxl_context_line ( struct intelxl_nic *intelxl,
00745                                   struct intelxl_context_line *line,
00746                                   unsigned int index, uint32_t op ) {
00747         uint32_t pfcm_lanctxctl;
00748         uint32_t pfcm_lanctxstat;
00749         unsigned int queue;
00750         unsigned int i;
00751 
00752         /* Write context data */
00753         for ( i = 0; i < ( sizeof ( *line ) / sizeof ( line->raw[0] ) ); i++ ) {
00754                 writel ( le32_to_cpu ( line->raw[i] ),
00755                          intelxl->regs + INTELXL_PFCM_LANCTXDATA ( i ) );
00756         }
00757 
00758         /* Start context operation */
00759         queue = ( intelxl->base + intelxl->queue );
00760         pfcm_lanctxctl = ( INTELXL_PFCM_LANCTXCTL_QUEUE_NUM ( queue ) |
00761                            INTELXL_PFCM_LANCTXCTL_SUB_LINE ( index ) |
00762                            INTELXL_PFCM_LANCTXCTL_OP_CODE_WRITE | op );
00763         writel ( pfcm_lanctxctl, intelxl->regs + INTELXL_PFCM_LANCTXCTL );
00764 
00765         /* Wait for operation to complete */
00766         for ( i = 0 ; i < INTELXL_CTX_MAX_WAIT_MS ; i++ ) {
00767 
00768                 /* Check if operation is complete */
00769                 pfcm_lanctxstat = readl ( intelxl->regs +
00770                                           INTELXL_PFCM_LANCTXSTAT );
00771                 if ( pfcm_lanctxstat & INTELXL_PFCM_LANCTXSTAT_DONE )
00772                         return 0;
00773 
00774                 /* Delay */
00775                 mdelay ( 1 );
00776         }
00777 
00778         DBGC ( intelxl, "INTELXL %p timed out waiting for context: %#08x\n",
00779                intelxl, pfcm_lanctxctl );
00780         return -ETIMEDOUT;
00781 }
00782 
00783 /**
00784  * Program queue context
00785  *
00786  * @v intelxl           Intel device
00787  * @v line              Queue context lines
00788  * @v len               Size of context
00789  * @v op                Context operation
00790  * @ret rc              Return status code
00791  */
00792 static int intelxl_context ( struct intelxl_nic *intelxl,
00793                              struct intelxl_context_line *line,
00794                              size_t len, uint32_t op ) {
00795         unsigned int index;
00796         int rc;
00797 
00798         DBGC2 ( intelxl, "INTELXL %p context %#08x len %#zx:\n",
00799                 intelxl, op, len );
00800         DBGC2_HDA ( intelxl, 0, line, len );
00801 
00802         /* Program one line at a time */
00803         for ( index = 0 ; ( sizeof ( *line ) * index ) < len ; index++ ) {
00804                 if ( ( rc = intelxl_context_line ( intelxl, line++, index,
00805                                                    op ) ) != 0 )
00806                         return rc;
00807         }
00808 
00809         return 0;
00810 }
00811 
00812 /**
00813  * Program transmit queue context
00814  *
00815  * @v intelxl           Intel device
00816  * @v address           Descriptor ring base address
00817  * @ret rc              Return status code
00818  */
00819 static int intelxl_context_tx ( struct intelxl_nic *intelxl,
00820                                 physaddr_t address ) {
00821         union {
00822                 struct intelxl_context_tx tx;
00823                 struct intelxl_context_line line;
00824         } ctx;
00825         int rc;
00826 
00827         /* Initialise context */
00828         memset ( &ctx, 0, sizeof ( ctx ) );
00829         ctx.tx.flags = cpu_to_le16 ( INTELXL_CTX_TX_FL_NEW );
00830         ctx.tx.base = cpu_to_le64 ( INTELXL_CTX_TX_BASE ( address ) );
00831         ctx.tx.count =
00832                 cpu_to_le16 ( INTELXL_CTX_TX_COUNT ( INTELXL_TX_NUM_DESC ) );
00833         ctx.tx.qset = INTELXL_CTX_TX_QSET ( intelxl->qset );
00834 
00835         /* Program context */
00836         if ( ( rc = intelxl_context ( intelxl, &ctx.line, sizeof ( ctx ),
00837                                       INTELXL_PFCM_LANCTXCTL_TYPE_TX ) ) != 0 )
00838                 return rc;
00839 
00840         return 0;
00841 }
00842 
00843 /**
00844  * Program receive queue context
00845  *
00846  * @v intelxl           Intel device
00847  * @v address           Descriptor ring base address
00848  * @ret rc              Return status code
00849  */
00850 static int intelxl_context_rx ( struct intelxl_nic *intelxl,
00851                                 physaddr_t address ) {
00852         union {
00853                 struct intelxl_context_rx rx;
00854                 struct intelxl_context_line line;
00855         } ctx;
00856         uint64_t base_count;
00857         int rc;
00858 
00859         /* Initialise context */
00860         memset ( &ctx, 0, sizeof ( ctx ) );
00861         base_count = INTELXL_CTX_RX_BASE_COUNT ( address, INTELXL_RX_NUM_DESC );
00862         ctx.rx.base_count = cpu_to_le64 ( base_count );
00863         ctx.rx.len = cpu_to_le16 ( INTELXL_CTX_RX_LEN ( intelxl->mfs ) );
00864         ctx.rx.flags = INTELXL_CTX_RX_FL_CRCSTRIP;
00865         ctx.rx.mfs = cpu_to_le16 ( INTELXL_CTX_RX_MFS ( intelxl->mfs ) );
00866 
00867         /* Program context */
00868         if ( ( rc = intelxl_context ( intelxl, &ctx.line, sizeof ( ctx ),
00869                                       INTELXL_PFCM_LANCTXCTL_TYPE_RX ) ) != 0 )
00870                 return rc;
00871 
00872         return 0;
00873 }
00874 
00875 /**
00876  * Enable descriptor ring
00877  *
00878  * @v intelxl           Intel device
00879  * @v ring              Descriptor ring
00880  * @ret rc              Return status code
00881  */
00882 static int intelxl_enable_ring ( struct intelxl_nic *intelxl,
00883                                  struct intelxl_ring *ring ) {
00884         void *ring_regs = ( intelxl->regs + ring->reg );
00885         uint32_t qxx_ena;
00886 
00887         /* Enable ring */
00888         writel ( INTELXL_QXX_ENA_REQ, ( ring_regs + INTELXL_QXX_ENA ) );
00889         udelay ( INTELXL_QUEUE_ENABLE_DELAY_US );
00890         qxx_ena = readl ( ring_regs + INTELXL_QXX_ENA );
00891         if ( ! ( qxx_ena & INTELXL_QXX_ENA_STAT ) ) {
00892                 DBGC ( intelxl, "INTELXL %p ring %06x failed to enable: "
00893                        "%#08x\n", intelxl, ring->reg, qxx_ena );
00894                 return -EIO;
00895         }
00896 
00897         return 0;
00898 }
00899 
00900 /**
00901  * Disable descriptor ring
00902  *
00903  * @v intelxl           Intel device
00904  * @v ring              Descriptor ring
00905  * @ret rc              Return status code
00906  */
00907 static int intelxl_disable_ring ( struct intelxl_nic *intelxl,
00908                                   struct intelxl_ring *ring ) {
00909         void *ring_regs = ( intelxl->regs + ring->reg );
00910         uint32_t qxx_ena;
00911         unsigned int i;
00912 
00913         /* Disable ring */
00914         writel ( 0, ( ring_regs + INTELXL_QXX_ENA ) );
00915 
00916         /* Wait for ring to be disabled */
00917         for ( i = 0 ; i < INTELXL_QUEUE_DISABLE_MAX_WAIT_MS ; i++ ) {
00918 
00919                 /* Check if ring is disabled */
00920                 qxx_ena = readl ( ring_regs + INTELXL_QXX_ENA );
00921                 if ( ! ( qxx_ena & INTELXL_QXX_ENA_STAT ) )
00922                         return 0;
00923 
00924                 /* Delay */
00925                 mdelay ( 1 );
00926         }
00927 
00928         DBGC ( intelxl, "INTELXL %p ring %06x timed out waiting for disable: "
00929                "%#08x\n", intelxl, ring->reg, qxx_ena );
00930         return -ETIMEDOUT;
00931 }
00932 
00933 /**
00934  * Create descriptor ring
00935  *
00936  * @v intelxl           Intel device
00937  * @v ring              Descriptor ring
00938  * @ret rc              Return status code
00939  */
00940 static int intelxl_create_ring ( struct intelxl_nic *intelxl,
00941                                  struct intelxl_ring *ring ) {
00942         void *ring_regs = ( intelxl->regs + ring->reg );
00943         physaddr_t address;
00944         int rc;
00945 
00946         /* Allocate descriptor ring */
00947         ring->desc = malloc_dma ( ring->len, INTELXL_ALIGN );
00948         if ( ! ring->desc ) {
00949                 rc = -ENOMEM;
00950                 goto err_alloc;
00951         }
00952 
00953         /* Initialise descriptor ring */
00954         memset ( ring->desc, 0, ring->len );
00955 
00956         /* Reset tail pointer */
00957         writel ( 0, ( ring_regs + INTELXL_QXX_TAIL ) );
00958 
00959         /* Program queue context */
00960         address = virt_to_bus ( ring->desc );
00961         if ( ( rc = ring->context ( intelxl, address ) ) != 0 )
00962                 goto err_context;
00963 
00964         /* Enable ring */
00965         if ( ( rc = intelxl_enable_ring ( intelxl, ring ) ) != 0 )
00966                 goto err_enable;
00967 
00968         /* Reset counters */
00969         ring->prod = 0;
00970         ring->cons = 0;
00971 
00972         DBGC ( intelxl, "INTELXL %p ring %06x is at [%08llx,%08llx)\n",
00973                intelxl, ring->reg, ( ( unsigned long long ) address ),
00974                ( ( unsigned long long ) address + ring->len ) );
00975 
00976         return 0;
00977 
00978         intelxl_disable_ring ( intelxl, ring );
00979  err_enable:
00980  err_context:
00981         free_dma ( ring->desc, ring->len );
00982  err_alloc:
00983         return rc;
00984 }
00985 
00986 /**
00987  * Destroy descriptor ring
00988  *
00989  * @v intelxl           Intel device
00990  * @v ring              Descriptor ring
00991  */
00992 static void intelxl_destroy_ring ( struct intelxl_nic *intelxl,
00993                                    struct intelxl_ring *ring ) {
00994         int rc;
00995 
00996         /* Disable ring */
00997         if ( ( rc = intelxl_disable_ring ( intelxl, ring ) ) != 0 ) {
00998                 /* Leak memory; there's nothing else we can do */
00999                 return;
01000         }
01001 
01002         /* Free descriptor ring */
01003         free_dma ( ring->desc, ring->len );
01004         ring->desc = NULL;
01005 }
01006 
01007 /**
01008  * Refill receive descriptor ring
01009  *
01010  * @v intelxl           Intel device
01011  */
01012 static void intelxl_refill_rx ( struct intelxl_nic *intelxl ) {
01013         struct intelxl_rx_data_descriptor *rx;
01014         struct io_buffer *iobuf;
01015         unsigned int rx_idx;
01016         unsigned int rx_tail;
01017         physaddr_t address;
01018         unsigned int refilled = 0;
01019 
01020         /* Refill ring */
01021         while ( ( intelxl->rx.prod - intelxl->rx.cons ) < INTELXL_RX_FILL ) {
01022 
01023                 /* Allocate I/O buffer */
01024                 iobuf = alloc_iob ( intelxl->mfs );
01025                 if ( ! iobuf ) {
01026                         /* Wait for next refill */
01027                         break;
01028                 }
01029 
01030                 /* Get next receive descriptor */
01031                 rx_idx = ( intelxl->rx.prod++ % INTELXL_RX_NUM_DESC );
01032                 rx = &intelxl->rx.desc[rx_idx].rx;
01033 
01034                 /* Populate receive descriptor */
01035                 address = virt_to_bus ( iobuf->data );
01036                 rx->address = cpu_to_le64 ( address );
01037                 rx->flags = 0;
01038 
01039                 /* Record I/O buffer */
01040                 assert ( intelxl->rx_iobuf[rx_idx] == NULL );
01041                 intelxl->rx_iobuf[rx_idx] = iobuf;
01042 
01043                 DBGC2 ( intelxl, "INTELXL %p RX %d is [%llx,%llx)\n", intelxl,
01044                         rx_idx, ( ( unsigned long long ) address ),
01045                         ( ( unsigned long long ) address + intelxl->mfs ) );
01046                 refilled++;
01047         }
01048 
01049         /* Push descriptors to card, if applicable */
01050         if ( refilled ) {
01051                 wmb();
01052                 rx_tail = ( intelxl->rx.prod % INTELXL_RX_NUM_DESC );
01053                 writel ( rx_tail,
01054                          ( intelxl->regs + intelxl->rx.reg + INTELXL_QXX_TAIL));
01055         }
01056 }
01057 
01058 /******************************************************************************
01059  *
01060  * Network device interface
01061  *
01062  ******************************************************************************
01063  */
01064 
01065 /**
01066  * Open network device
01067  *
01068  * @v netdev            Network device
01069  * @ret rc              Return status code
01070  */
01071 static int intelxl_open ( struct net_device *netdev ) {
01072         struct intelxl_nic *intelxl = netdev->priv;
01073         union intelxl_receive_address mac;
01074         unsigned int queue;
01075         uint32_t prtgl_sal;
01076         uint32_t prtgl_sah;
01077         int rc;
01078 
01079         /* Calculate maximum frame size */
01080         intelxl->mfs = ( ( ETH_HLEN + netdev->mtu + 4 /* CRC */ +
01081                            INTELXL_ALIGN - 1 ) & ~( INTELXL_ALIGN - 1 ) );
01082 
01083         /* Program MAC address and maximum frame size */
01084         memset ( &mac, 0, sizeof ( mac ) );
01085         memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) );
01086         prtgl_sal = le32_to_cpu ( mac.reg.low );
01087         prtgl_sah = ( le32_to_cpu ( mac.reg.high ) |
01088                       INTELXL_PRTGL_SAH_MFS_SET ( intelxl->mfs ) );
01089         writel ( prtgl_sal, intelxl->regs + INTELXL_PRTGL_SAL );
01090         writel ( prtgl_sah, intelxl->regs + INTELXL_PRTGL_SAH );
01091 
01092         /* Associate transmit queue to PF */
01093         writel ( ( INTELXL_QXX_CTL_PFVF_Q_PF |
01094                    INTELXL_QXX_CTL_PFVF_PF_INDX ( intelxl->pf ) ),
01095                  ( intelxl->regs + intelxl->tx.reg + INTELXL_QXX_CTL ) );
01096 
01097         /* Clear transmit pre queue disable */
01098         queue = ( intelxl->base + intelxl->queue );
01099         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_CLEAR_QDIS |
01100                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01101                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01102 
01103         /* Reset transmit queue head */
01104         writel ( 0, ( intelxl->regs + INTELXL_QTX_HEAD ( intelxl->queue ) ) );
01105 
01106         /* Create receive descriptor ring */
01107         if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->rx ) ) != 0 )
01108                 goto err_create_rx;
01109 
01110         /* Create transmit descriptor ring */
01111         if ( ( rc = intelxl_create_ring ( intelxl, &intelxl->tx ) ) != 0 )
01112                 goto err_create_tx;
01113 
01114         /* Fill receive ring */
01115         intelxl_refill_rx ( intelxl );
01116 
01117         /* Restart autonegotiation */
01118         intelxl_admin_autoneg ( intelxl );
01119 
01120         /* Update link state */
01121         intelxl_admin_link ( netdev );
01122 
01123         return 0;
01124 
01125         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_SET_QDIS |
01126                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01127                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01128         udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
01129         intelxl_destroy_ring ( intelxl, &intelxl->tx );
01130  err_create_tx:
01131         intelxl_destroy_ring ( intelxl, &intelxl->rx );
01132  err_create_rx:
01133         return rc;
01134 }
01135 
01136 /**
01137  * Close network device
01138  *
01139  * @v netdev            Network device
01140  */
01141 static void intelxl_close ( struct net_device *netdev ) {
01142         struct intelxl_nic *intelxl = netdev->priv;
01143         unsigned int queue;
01144         unsigned int i;
01145 
01146         /* Dump contexts (for debugging) */
01147         intelxl_context_dump ( intelxl, INTELXL_PFCM_LANCTXCTL_TYPE_TX,
01148                                sizeof ( struct intelxl_context_tx ) );
01149         intelxl_context_dump ( intelxl, INTELXL_PFCM_LANCTXCTL_TYPE_RX,
01150                                sizeof ( struct intelxl_context_rx ) );
01151 
01152         /* Pre-disable transmit queue */
01153         queue = ( intelxl->base + intelxl->queue );
01154         writel ( ( INTELXL_GLLAN_TXPRE_QDIS_SET_QDIS |
01155                    INTELXL_GLLAN_TXPRE_QDIS_QINDX ( queue ) ),
01156                  ( intelxl->regs + INTELXL_GLLAN_TXPRE_QDIS ( queue ) ) );
01157         udelay ( INTELXL_QUEUE_PRE_DISABLE_DELAY_US );
01158 
01159         /* Destroy transmit descriptor ring */
01160         intelxl_destroy_ring ( intelxl, &intelxl->tx );
01161 
01162         /* Destroy receive descriptor ring */
01163         intelxl_destroy_ring ( intelxl, &intelxl->rx );
01164 
01165         /* Discard any unused receive buffers */
01166         for ( i = 0 ; i < INTELXL_RX_NUM_DESC ; i++ ) {
01167                 if ( intelxl->rx_iobuf[i] )
01168                         free_iob ( intelxl->rx_iobuf[i] );
01169                 intelxl->rx_iobuf[i] = NULL;
01170         }
01171 }
01172 
01173 /**
01174  * Transmit packet
01175  *
01176  * @v netdev            Network device
01177  * @v iobuf             I/O buffer
01178  * @ret rc              Return status code
01179  */
01180 static int intelxl_transmit ( struct net_device *netdev,
01181                               struct io_buffer *iobuf ) {
01182         struct intelxl_nic *intelxl = netdev->priv;
01183         struct intelxl_tx_data_descriptor *tx;
01184         unsigned int tx_idx;
01185         unsigned int tx_tail;
01186         physaddr_t address;
01187         size_t len;
01188 
01189         /* Get next transmit descriptor */
01190         if ( ( intelxl->tx.prod - intelxl->tx.cons ) >= INTELXL_TX_FILL ) {
01191                 DBGC ( intelxl, "INTELXL %p out of transmit descriptors\n",
01192                        intelxl );
01193                 return -ENOBUFS;
01194         }
01195         tx_idx = ( intelxl->tx.prod++ % INTELXL_TX_NUM_DESC );
01196         tx_tail = ( intelxl->tx.prod % INTELXL_TX_NUM_DESC );
01197         tx = &intelxl->tx.desc[tx_idx].tx;
01198 
01199         /* Populate transmit descriptor */
01200         address = virt_to_bus ( iobuf->data );
01201         len = iob_len ( iobuf );
01202         tx->address = cpu_to_le64 ( address );
01203         tx->len = cpu_to_le32 ( INTELXL_TX_DATA_LEN ( len ) );
01204         tx->flags = cpu_to_le32 ( INTELXL_TX_DATA_DTYP | INTELXL_TX_DATA_EOP |
01205                                   INTELXL_TX_DATA_RS | INTELXL_TX_DATA_JFDI );
01206         wmb();
01207 
01208         /* Notify card that there are packets ready to transmit */
01209         writel ( tx_tail,
01210                  ( intelxl->regs + intelxl->tx.reg + INTELXL_QXX_TAIL ) );
01211 
01212         DBGC2 ( intelxl, "INTELXL %p TX %d is [%llx,%llx)\n", intelxl, tx_idx,
01213                 ( ( unsigned long long ) address ),
01214                 ( ( unsigned long long ) address + len ) );
01215         return 0;
01216 }
01217 
01218 /**
01219  * Poll for completed packets
01220  *
01221  * @v netdev            Network device
01222  */
01223 static void intelxl_poll_tx ( struct net_device *netdev ) {
01224         struct intelxl_nic *intelxl = netdev->priv;
01225         struct intelxl_tx_writeback_descriptor *tx_wb;
01226         unsigned int tx_idx;
01227 
01228         /* Check for completed packets */
01229         while ( intelxl->tx.cons != intelxl->tx.prod ) {
01230 
01231                 /* Get next transmit descriptor */
01232                 tx_idx = ( intelxl->tx.cons % INTELXL_TX_NUM_DESC );
01233                 tx_wb = &intelxl->tx.desc[tx_idx].tx_wb;
01234 
01235                 /* Stop if descriptor is still in use */
01236                 if ( ! ( tx_wb->flags & INTELXL_TX_WB_FL_DD ) )
01237                         return;
01238                 DBGC2 ( intelxl, "INTELXL %p TX %d complete\n",
01239                         intelxl, tx_idx );
01240 
01241                 /* Complete TX descriptor */
01242                 netdev_tx_complete_next ( netdev );
01243                 intelxl->tx.cons++;
01244         }
01245 }
01246 
01247 /**
01248  * Poll for received packets
01249  *
01250  * @v netdev            Network device
01251  */
01252 static void intelxl_poll_rx ( struct net_device *netdev ) {
01253         struct intelxl_nic *intelxl = netdev->priv;
01254         struct intelxl_rx_writeback_descriptor *rx_wb;
01255         struct io_buffer *iobuf;
01256         unsigned int rx_idx;
01257         size_t len;
01258 
01259         /* Check for received packets */
01260         while ( intelxl->rx.cons != intelxl->rx.prod ) {
01261 
01262                 /* Get next receive descriptor */
01263                 rx_idx = ( intelxl->rx.cons % INTELXL_RX_NUM_DESC );
01264                 rx_wb = &intelxl->rx.desc[rx_idx].rx_wb;
01265 
01266                 /* Stop if descriptor is still in use */
01267                 if ( ! ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_DD ) ) )
01268                         return;
01269 
01270                 /* Populate I/O buffer */
01271                 iobuf = intelxl->rx_iobuf[rx_idx];
01272                 intelxl->rx_iobuf[rx_idx] = NULL;
01273                 len = INTELXL_RX_WB_LEN ( le32_to_cpu ( rx_wb->len ) );
01274                 iob_put ( iobuf, len );
01275 
01276                 /* Hand off to network stack */
01277                 if ( rx_wb->flags & cpu_to_le32 ( INTELXL_RX_WB_FL_RXE ) ) {
01278                         DBGC ( intelxl, "INTELXL %p RX %d error (length %zd, "
01279                                "flags %08x)\n", intelxl, rx_idx, len,
01280                                le32_to_cpu ( rx_wb->flags ) );
01281                         netdev_rx_err ( netdev, iobuf, -EIO );
01282                 } else {
01283                         DBGC2 ( intelxl, "INTELXL %p RX %d complete (length "
01284                                 "%zd)\n", intelxl, rx_idx, len );
01285                         netdev_rx ( netdev, iobuf );
01286                 }
01287                 intelxl->rx.cons++;
01288         }
01289 }
01290 
01291 /**
01292  * Poll for completed and received packets
01293  *
01294  * @v netdev            Network device
01295  */
01296 static void intelxl_poll ( struct net_device *netdev ) {
01297         struct intelxl_nic *intelxl = netdev->priv;
01298 
01299         /* Acknowledge interrupts, if applicable */
01300         if ( netdev_irq_enabled ( netdev ) ) {
01301                 writel ( ( INTELXL_PFINT_DYN_CTL0_CLEARPBA |
01302                            INTELXL_PFINT_DYN_CTL0_INTENA_MASK ),
01303                          intelxl->regs + INTELXL_PFINT_DYN_CTL0 );
01304         }
01305 
01306         /* Poll for completed packets */
01307         intelxl_poll_tx ( netdev );
01308 
01309         /* Poll for received packets */
01310         intelxl_poll_rx ( netdev );
01311 
01312         /* Poll for admin events */
01313         intelxl_poll_admin ( netdev );
01314 
01315         /* Refill RX ring */
01316         intelxl_refill_rx ( intelxl );
01317 }
01318 
01319 /**
01320  * Enable or disable interrupts
01321  *
01322  * @v netdev            Network device
01323  * @v enable            Interrupts should be enabled
01324  */
01325 static void intelxl_irq ( struct net_device *netdev, int enable ) {
01326         struct intelxl_nic *intelxl = netdev->priv;
01327 
01328         if ( enable ) {
01329                 writel ( INTELXL_PFINT_DYN_CTL0_INTENA,
01330                          intelxl->regs + INTELXL_PFINT_DYN_CTL0 );
01331         } else {
01332                 writel ( 0, intelxl->regs + INTELXL_PFINT_DYN_CTL0 );
01333         }
01334 }
01335 
01336 /** Network device operations */
01337 static struct net_device_operations intelxl_operations = {
01338         .open           = intelxl_open,
01339         .close          = intelxl_close,
01340         .transmit       = intelxl_transmit,
01341         .poll           = intelxl_poll,
01342         .irq            = intelxl_irq,
01343 };
01344 
01345 /******************************************************************************
01346  *
01347  * PCI interface
01348  *
01349  ******************************************************************************
01350  */
01351 
01352 /**
01353  * Probe PCI device
01354  *
01355  * @v pci               PCI device
01356  * @ret rc              Return status code
01357  */
01358 static int intelxl_probe ( struct pci_device *pci ) {
01359         struct net_device *netdev;
01360         struct intelxl_nic *intelxl;
01361         uint32_t pfgen_portnum;
01362         uint32_t pflan_qalloc;
01363         int rc;
01364 
01365         /* Allocate and initialise net device */
01366         netdev = alloc_etherdev ( sizeof ( *intelxl ) );
01367         if ( ! netdev ) {
01368                 rc = -ENOMEM;
01369                 goto err_alloc;
01370         }
01371         netdev_init ( netdev, &intelxl_operations );
01372         intelxl = netdev->priv;
01373         pci_set_drvdata ( pci, netdev );
01374         netdev->dev = &pci->dev;
01375         memset ( intelxl, 0, sizeof ( *intelxl ) );
01376         intelxl->pf = PCI_FUNC ( pci->busdevfn );
01377         intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD );
01378         intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT );
01379         intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC,
01380                             intelxl_context_tx );
01381         intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC,
01382                             intelxl_context_rx );
01383 
01384         /* Fix up PCI device */
01385         adjust_pci_device ( pci );
01386 
01387         /* Map registers */
01388         intelxl->regs = ioremap ( pci->membase, INTELXL_BAR_SIZE );
01389         if ( ! intelxl->regs ) {
01390                 rc = -ENODEV;
01391                 goto err_ioremap;
01392         }
01393 
01394         /* Reset the NIC */
01395         if ( ( rc = intelxl_reset ( intelxl ) ) != 0 )
01396                 goto err_reset;
01397 
01398         /* Get port number and base queue number */
01399         pfgen_portnum = readl ( intelxl->regs + INTELXL_PFGEN_PORTNUM );
01400         intelxl->port = INTELXL_PFGEN_PORTNUM_PORT_NUM ( pfgen_portnum );
01401         pflan_qalloc = readl ( intelxl->regs + INTELXL_PFLAN_QALLOC );
01402         intelxl->base = INTELXL_PFLAN_QALLOC_FIRSTQ ( pflan_qalloc );
01403         DBGC ( intelxl, "INTELXL %p PF %d using port %d queues [%#04x-%#04x]\n",
01404                intelxl, intelxl->pf, intelxl->port, intelxl->base,
01405                INTELXL_PFLAN_QALLOC_LASTQ ( pflan_qalloc ) );
01406 
01407         /* Fetch MAC address and maximum frame size */
01408         if ( ( rc = intelxl_fetch_mac ( intelxl, netdev ) ) != 0 )
01409                 goto err_fetch_mac;
01410 
01411         /* Open admin queues */
01412         if ( ( rc = intelxl_open_admin ( intelxl ) ) != 0 )
01413                 goto err_open_admin;
01414 
01415         /* Get switch configuration */
01416         if ( ( rc = intelxl_admin_switch ( intelxl ) ) != 0 )
01417                 goto err_admin_switch;
01418 
01419         /* Get VSI configuration */
01420         if ( ( rc = intelxl_admin_vsi ( intelxl ) ) != 0 )
01421                 goto err_admin_vsi;
01422 
01423         /* Configure switch for promiscuous mode */
01424         if ( ( rc = intelxl_admin_promisc ( intelxl ) ) != 0 )
01425                 goto err_admin_promisc;
01426 
01427         /* Configure queue register addresses */
01428         intelxl->tx.reg = INTELXL_QTX ( intelxl->queue );
01429         intelxl->rx.reg = INTELXL_QRX ( intelxl->queue );
01430 
01431         /* Configure interrupt causes */
01432         writel ( ( INTELXL_QINT_TQCTL_NEXTQ_INDX_NONE |
01433                    INTELXL_QINT_TQCTL_CAUSE_ENA ),
01434                  intelxl->regs + INTELXL_QINT_TQCTL ( intelxl->queue ) );
01435         writel ( ( INTELXL_QINT_RQCTL_NEXTQ_INDX ( intelxl->queue ) |
01436                    INTELXL_QINT_RQCTL_NEXTQ_TYPE_TX |
01437                    INTELXL_QINT_RQCTL_CAUSE_ENA ),
01438                  intelxl->regs + INTELXL_QINT_RQCTL ( intelxl->queue ) );
01439         writel ( ( INTELXL_PFINT_LNKLST0_FIRSTQ_INDX ( intelxl->queue ) |
01440                    INTELXL_PFINT_LNKLST0_FIRSTQ_TYPE_RX ),
01441                  intelxl->regs + INTELXL_PFINT_LNKLST0 );
01442         writel ( INTELXL_PFINT_ICR0_ENA_ADMINQ,
01443                  intelxl->regs + INTELXL_PFINT_ICR0_ENA );
01444 
01445         /* Register network device */
01446         if ( ( rc = register_netdev ( netdev ) ) != 0 )
01447                 goto err_register_netdev;
01448 
01449         /* Set initial link state */
01450         intelxl_admin_link ( netdev );
01451 
01452         return 0;
01453 
01454         unregister_netdev ( netdev );
01455  err_register_netdev:
01456  err_admin_promisc:
01457  err_admin_vsi:
01458  err_admin_switch:
01459         intelxl_close_admin ( intelxl );
01460  err_open_admin:
01461  err_fetch_mac:
01462         intelxl_reset ( intelxl );
01463  err_reset:
01464         iounmap ( intelxl->regs );
01465  err_ioremap:
01466         netdev_nullify ( netdev );
01467         netdev_put ( netdev );
01468  err_alloc:
01469         return rc;
01470 }
01471 
01472 /**
01473  * Remove PCI device
01474  *
01475  * @v pci               PCI device
01476  */
01477 static void intelxl_remove ( struct pci_device *pci ) {
01478         struct net_device *netdev = pci_get_drvdata ( pci );
01479         struct intelxl_nic *intelxl = netdev->priv;
01480 
01481         /* Unregister network device */
01482         unregister_netdev ( netdev );
01483 
01484         /* Close admin queues */
01485         intelxl_close_admin ( intelxl );
01486 
01487         /* Reset the NIC */
01488         intelxl_reset ( intelxl );
01489 
01490         /* Free network device */
01491         iounmap ( intelxl->regs );
01492         netdev_nullify ( netdev );
01493         netdev_put ( netdev );
01494 }
01495 
01496 /** PCI device IDs */
01497 static struct pci_device_id intelxl_nics[] = {
01498         PCI_ROM ( 0x8086, 0x1572, "x710-sfp", "X710 10GbE SFP+", 0 ),
01499         PCI_ROM ( 0x8086, 0x1574, "xl710-qemu", "Virtual XL710", 0 ),
01500         PCI_ROM ( 0x8086, 0x1580, "xl710-kx-b", "XL710 40GbE backplane", 0 ),
01501         PCI_ROM ( 0x8086, 0x1581, "xl710-kx-c", "XL710 10GbE backplane", 0 ),
01502         PCI_ROM ( 0x8086, 0x1583, "xl710-qda2", "XL710 40GbE QSFP+", 0 ),
01503         PCI_ROM ( 0x8086, 0x1584, "xl710-qda1", "XL710 40GbE QSFP+", 0 ),
01504         PCI_ROM ( 0x8086, 0x1585, "x710-qsfp", "X710 10GbE QSFP+", 0 ),
01505         PCI_ROM ( 0x8086, 0x1586, "x710-10gt", "X710 10GBASE-T", 0 ),
01506         PCI_ROM ( 0x8086, 0x1587, "x710-kr2", "XL710 20GbE backplane", 0 ),
01507         PCI_ROM ( 0x8086, 0x1588, "x710-kr2-a", "XL710 20GbE backplane", 0 ),
01508         PCI_ROM ( 0x8086, 0x1589, "x710-10gt4", "X710 10GBASE-T4", 0 ),
01509         PCI_ROM ( 0x8086, 0x158a, "xxv710", "XXV710 25GbE backplane", 0 ),
01510         PCI_ROM ( 0x8086, 0x158b, "xxv710-sfp28", "XXV710 25GbE SFP28", 0 ),
01511         PCI_ROM ( 0x8086, 0x37ce, "x722-kx", "X722 10GbE backplane", 0 ),
01512         PCI_ROM ( 0x8086, 0x37cf, "x722-qsfp", "X722 10GbE QSFP+", 0 ),
01513         PCI_ROM ( 0x8086, 0x37d0, "x722-sfp", "X722 10GbE SFP+", 0 ),
01514         PCI_ROM ( 0x8086, 0x37d1, "x722-1gt", "X722 1GBASE-T", 0 ),
01515         PCI_ROM ( 0x8086, 0x37d2, "x722-10gt", "X722 10GBASE-T", 0 ),
01516         PCI_ROM ( 0x8086, 0x37d3, "x722-sfp-i", "X722 10GbE SFP+", 0 ),
01517 };
01518 
01519 /** PCI driver */
01520 struct pci_driver intelxl_driver __pci_driver = {
01521         .ids = intelxl_nics,
01522         .id_count = ( sizeof ( intelxl_nics ) / sizeof ( intelxl_nics[0] ) ),
01523         .probe = intelxl_probe,
01524         .remove = intelxl_remove,
01525 };