iPXE
smscusb.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2017 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 <string.h>
00027 #include <errno.h>
00028 #include <unistd.h>
00029 #include <ipxe/usb.h>
00030 #include <ipxe/usbnet.h>
00031 #include <ipxe/ethernet.h>
00032 #include <ipxe/profile.h>
00033 #include <ipxe/fdt.h>
00034 #include "smscusb.h"
00035 
00036 /** @file
00037  *
00038  * SMSC USB Ethernet drivers
00039  *
00040  */
00041 
00042 /** Interrupt completion profiler */
00043 static struct profiler smscusb_intr_profiler __profiler =
00044         { .name = "smscusb.intr" };
00045 
00046 /******************************************************************************
00047  *
00048  * Register access
00049  *
00050  ******************************************************************************
00051  */
00052 
00053 /**
00054  * Write register (without byte-swapping)
00055  *
00056  * @v smscusb           Smscusb device
00057  * @v address           Register address
00058  * @v value             Register value
00059  * @ret rc              Return status code
00060  */
00061 int smscusb_raw_writel ( struct smscusb_device *smscusb, unsigned int address,
00062                          uint32_t value ) {
00063         int rc;
00064 
00065         /* Write register */
00066         DBGCIO ( smscusb, "SMSCUSB %p [%03x] <= %08x\n",
00067                  smscusb, address, le32_to_cpu ( value ) );
00068         if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_WRITE, 0,
00069                                   address, &value, sizeof ( value ) ) ) != 0 ) {
00070                 DBGC ( smscusb, "SMSCUSB %p could not write %03x: %s\n",
00071                        smscusb, address, strerror ( rc ) );
00072                 return rc;
00073         }
00074 
00075         return 0;
00076 }
00077 
00078 /**
00079  * Read register (without byte-swapping)
00080  *
00081  * @v smscusb           SMSC USB device
00082  * @v address           Register address
00083  * @ret value           Register value
00084  * @ret rc              Return status code
00085  */
00086 int smscusb_raw_readl ( struct smscusb_device *smscusb, unsigned int address,
00087                         uint32_t *value ) {
00088         int rc;
00089 
00090         /* Read register */
00091         if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_READ, 0,
00092                                   address, value, sizeof ( *value ) ) ) != 0 ) {
00093                 DBGC ( smscusb, "SMSCUSB %p could not read %03x: %s\n",
00094                        smscusb, address, strerror ( rc ) );
00095                 return rc;
00096         }
00097         DBGCIO ( smscusb, "SMSCUSB %p [%03x] => %08x\n",
00098                  smscusb, address, le32_to_cpu ( *value ) );
00099 
00100         return 0;
00101 }
00102 
00103 /******************************************************************************
00104  *
00105  * EEPROM access
00106  *
00107  ******************************************************************************
00108  */
00109 
00110 /**
00111  * Wait for EEPROM to become idle
00112  *
00113  * @v smscusb           SMSC USB device
00114  * @v e2p_base          E2P register base
00115  * @ret rc              Return status code
00116  */
00117 static int smscusb_eeprom_wait ( struct smscusb_device *smscusb,
00118                                  unsigned int e2p_base ) {
00119         uint32_t e2p_cmd;
00120         unsigned int i;
00121         int rc;
00122 
00123         /* Wait for EPC_BSY to become clear */
00124         for ( i = 0 ; i < SMSCUSB_EEPROM_MAX_WAIT_MS ; i++ ) {
00125 
00126                 /* Read E2P_CMD and check EPC_BSY */
00127                 if ( ( rc = smscusb_readl ( smscusb,
00128                                             ( e2p_base + SMSCUSB_E2P_CMD ),
00129                                             &e2p_cmd ) ) != 0 )
00130                         return rc;
00131                 if ( ! ( e2p_cmd & SMSCUSB_E2P_CMD_EPC_BSY ) )
00132                         return 0;
00133 
00134                 /* Delay */
00135                 mdelay ( 1 );
00136         }
00137 
00138         DBGC ( smscusb, "SMSCUSB %p timed out waiting for EEPROM\n",
00139                smscusb );
00140         return -ETIMEDOUT;
00141 }
00142 
00143 /**
00144  * Read byte from EEPROM
00145  *
00146  * @v smscusb           SMSC USB device
00147  * @v e2p_base          E2P register base
00148  * @v address           EEPROM address
00149  * @ret byte            Byte read, or negative error
00150  */
00151 static int smscusb_eeprom_read_byte ( struct smscusb_device *smscusb,
00152                                       unsigned int e2p_base,
00153                                       unsigned int address ) {
00154         uint32_t e2p_cmd;
00155         uint32_t e2p_data;
00156         int rc;
00157 
00158         /* Wait for EEPROM to become idle */
00159         if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
00160                 return rc;
00161 
00162         /* Initiate read command */
00163         e2p_cmd = ( SMSCUSB_E2P_CMD_EPC_BSY | SMSCUSB_E2P_CMD_EPC_CMD_READ |
00164                     SMSCUSB_E2P_CMD_EPC_ADDR ( address ) );
00165         if ( ( rc = smscusb_writel ( smscusb, ( e2p_base + SMSCUSB_E2P_CMD ),
00166                                      e2p_cmd ) ) != 0 )
00167                 return rc;
00168 
00169         /* Wait for command to complete */
00170         if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
00171                 return rc;
00172 
00173         /* Read EEPROM data */
00174         if ( ( rc = smscusb_readl ( smscusb, ( e2p_base + SMSCUSB_E2P_DATA ),
00175                                     &e2p_data ) ) != 0 )
00176                 return rc;
00177 
00178         return SMSCUSB_E2P_DATA_GET ( e2p_data );
00179 }
00180 
00181 /**
00182  * Read data from EEPROM
00183  *
00184  * @v smscusb           SMSC USB device
00185  * @v e2p_base          E2P register base
00186  * @v address           EEPROM address
00187  * @v data              Data buffer
00188  * @v len               Length of data
00189  * @ret rc              Return status code
00190  */
00191 static int smscusb_eeprom_read ( struct smscusb_device *smscusb,
00192                                  unsigned int e2p_base, unsigned int address,
00193                                  void *data, size_t len ) {
00194         uint8_t *bytes;
00195         int byte;
00196 
00197         /* Read bytes */
00198         for ( bytes = data ; len-- ; address++, bytes++ ) {
00199                 byte = smscusb_eeprom_read_byte ( smscusb, e2p_base, address );
00200                 if ( byte < 0 )
00201                         return byte;
00202                 *bytes = byte;
00203         }
00204 
00205         return 0;
00206 }
00207 
00208 /**
00209  * Fetch MAC address from EEPROM
00210  *
00211  * @v smscusb           SMSC USB device
00212  * @v e2p_base          E2P register base
00213  * @ret rc              Return status code
00214  */
00215 int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb,
00216                                unsigned int e2p_base ) {
00217         struct net_device *netdev = smscusb->netdev;
00218         int rc;
00219 
00220         /* Read MAC address from EEPROM */
00221         if ( ( rc = smscusb_eeprom_read ( smscusb, e2p_base, SMSCUSB_EEPROM_MAC,
00222                                           netdev->hw_addr, ETH_ALEN ) ) != 0 )
00223                 return rc;
00224 
00225         /* Check that EEPROM is physically present */
00226         if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
00227                 DBGC ( smscusb, "SMSCUSB %p has no EEPROM MAC (%s)\n",
00228                        smscusb, eth_ntoa ( netdev->hw_addr ) );
00229                 return -ENODEV;
00230         }
00231 
00232         DBGC ( smscusb, "SMSCUSB %p using EEPROM MAC %s\n",
00233                smscusb, eth_ntoa ( netdev->hw_addr ) );
00234         return 0;
00235 }
00236 
00237 /******************************************************************************
00238  *
00239  * OTP access
00240  *
00241  ******************************************************************************
00242  */
00243 
00244 /**
00245  * Power up OTP
00246  *
00247  * @v smscusb           SMSC USB device
00248  * @v otp_base          OTP register base
00249  * @ret rc              Return status code
00250  */
00251 static int smscusb_otp_power_up ( struct smscusb_device *smscusb,
00252                                   unsigned int otp_base ) {
00253         uint32_t otp_power;
00254         unsigned int i;
00255         int rc;
00256 
00257         /* Power up OTP */
00258         if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_POWER ),
00259                                      0 ) ) != 0 )
00260                 return rc;
00261 
00262         /* Wait for OTP_POWER_DOWN to become clear */
00263         for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {
00264 
00265                 /* Read OTP_POWER and check OTP_POWER_DOWN */
00266                 if ( ( rc = smscusb_readl ( smscusb,
00267                                             ( otp_base + SMSCUSB_OTP_POWER ),
00268                                             &otp_power ) ) != 0 )
00269                         return rc;
00270                 if ( ! ( otp_power & SMSCUSB_OTP_POWER_DOWN ) )
00271                         return 0;
00272 
00273                 /* Delay */
00274                 mdelay ( 1 );
00275         }
00276 
00277         DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP power up\n",
00278                smscusb );
00279         return -ETIMEDOUT;
00280 }
00281 
00282 /**
00283  * Wait for OTP to become idle
00284  *
00285  * @v smscusb           SMSC USB device
00286  * @v otp_base          OTP register base
00287  * @ret rc              Return status code
00288  */
00289 static int smscusb_otp_wait ( struct smscusb_device *smscusb,
00290                               unsigned int otp_base ) {
00291         uint32_t otp_status;
00292         unsigned int i;
00293         int rc;
00294 
00295         /* Wait for OTP_STATUS_BUSY to become clear */
00296         for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {
00297 
00298                 /* Read OTP_STATUS and check OTP_STATUS_BUSY */
00299                 if ( ( rc = smscusb_readl ( smscusb,
00300                                             ( otp_base + SMSCUSB_OTP_STATUS ),
00301                                             &otp_status ) ) != 0 )
00302                         return rc;
00303                 if ( ! ( otp_status & SMSCUSB_OTP_STATUS_BUSY ) )
00304                         return 0;
00305 
00306                 /* Delay */
00307                 mdelay ( 1 );
00308         }
00309 
00310         DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP\n",
00311                smscusb );
00312         return -ETIMEDOUT;
00313 }
00314 
00315 /**
00316  * Read byte from OTP
00317  *
00318  * @v smscusb           SMSC USB device
00319  * @v otp_base          OTP register base
00320  * @v address           OTP address
00321  * @ret byte            Byte read, or negative error
00322  */
00323 static int smscusb_otp_read_byte ( struct smscusb_device *smscusb,
00324                                    unsigned int otp_base,
00325                                    unsigned int address ) {
00326         uint8_t addrh = ( address >> 8 );
00327         uint8_t addrl = ( address >> 0 );
00328         uint32_t otp_data;
00329         int rc;
00330 
00331         /* Wait for OTP to become idle */
00332         if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
00333                 return rc;
00334 
00335         /* Initiate read command */
00336         if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRH ),
00337                                      addrh ) ) != 0 )
00338                 return rc;
00339         if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRL ),
00340                                      addrl ) ) != 0 )
00341                 return rc;
00342         if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_CMD ),
00343                                      SMSCUSB_OTP_CMD_READ ) ) != 0 )
00344                 return rc;
00345         if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_GO ),
00346                                      SMSCUSB_OTP_GO_GO ) ) != 0 )
00347                 return rc;
00348 
00349         /* Wait for command to complete */
00350         if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
00351                 return rc;
00352 
00353         /* Read OTP data */
00354         if ( ( rc = smscusb_readl ( smscusb, ( otp_base + SMSCUSB_OTP_DATA ),
00355                                     &otp_data ) ) != 0 )
00356                 return rc;
00357 
00358         return SMSCUSB_OTP_DATA_GET ( otp_data );
00359 }
00360 
00361 /**
00362  * Read data from OTP
00363  *
00364  * @v smscusb           SMSC USB device
00365  * @v otp_base          OTP register base
00366  * @v address           OTP address
00367  * @v data              Data buffer
00368  * @v len               Length of data
00369  * @ret rc              Return status code
00370  */
00371 static int smscusb_otp_read ( struct smscusb_device *smscusb,
00372                               unsigned int otp_base, unsigned int address,
00373                               void *data, size_t len ) {
00374         uint8_t *bytes;
00375         int byte;
00376         int rc;
00377 
00378         /* Power up OTP */
00379         if ( ( rc = smscusb_otp_power_up ( smscusb, otp_base ) ) != 0 )
00380                 return rc;
00381 
00382         /* Read bytes */
00383         for ( bytes = data ; len-- ; address++, bytes++ ) {
00384                 byte = smscusb_otp_read_byte ( smscusb, otp_base, address );
00385                 if ( byte < 0 )
00386                         return byte;
00387                 *bytes = byte;
00388         }
00389 
00390         return 0;
00391 }
00392 
00393 /**
00394  * Fetch MAC address from OTP
00395  *
00396  * @v smscusb           SMSC USB device
00397  * @v otp_base          OTP register base
00398  * @ret rc              Return status code
00399  */
00400 int smscusb_otp_fetch_mac ( struct smscusb_device *smscusb,
00401                             unsigned int otp_base ) {
00402         struct net_device *netdev = smscusb->netdev;
00403         uint8_t signature;
00404         unsigned int address;
00405         int rc;
00406 
00407         /* Read OTP signature byte */
00408         if ( ( rc = smscusb_otp_read ( smscusb, otp_base, 0, &signature,
00409                                        sizeof ( signature ) ) ) != 0 )
00410                 return rc;
00411 
00412         /* Determine location of MAC address */
00413         switch ( signature ) {
00414         case SMSCUSB_OTP_1_SIG:
00415                 address = SMSCUSB_OTP_1_MAC;
00416                 break;
00417         case SMSCUSB_OTP_2_SIG:
00418                 address = SMSCUSB_OTP_2_MAC;
00419                 break;
00420         default:
00421                 DBGC ( smscusb, "SMSCUSB %p unknown OTP signature %#02x\n",
00422                        smscusb, signature );
00423                 return -ENOTSUP;
00424         }
00425 
00426         /* Read MAC address from OTP */
00427         if ( ( rc = smscusb_otp_read ( smscusb, otp_base, address,
00428                                        netdev->hw_addr, ETH_ALEN ) ) != 0 )
00429                 return rc;
00430 
00431         /* Check that OTP is valid */
00432         if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
00433                 DBGC ( smscusb, "SMSCUSB %p has no layout %#02x OTP MAC (%s)\n",
00434                        smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
00435                 return -ENODEV;
00436         }
00437 
00438         DBGC ( smscusb, "SMSCUSB %p using layout %#02x OTP MAC %s\n",
00439                smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
00440         return 0;
00441 }
00442 
00443 /******************************************************************************
00444  *
00445  * Device tree
00446  *
00447  ******************************************************************************
00448  */
00449 
00450 /**
00451  * Fetch MAC address from device tree
00452  *
00453  * @v smscusb           SMSC USB device
00454  * @ret rc              Return status code
00455  */
00456 int smscusb_fdt_fetch_mac ( struct smscusb_device *smscusb ) {
00457         struct net_device *netdev = smscusb->netdev;
00458         unsigned int offset;
00459         int rc;
00460 
00461         /* Look for "ethernet[0]" alias */
00462         if ( ( rc = fdt_alias ( "ethernet", &offset ) != 0 ) &&
00463              ( rc = fdt_alias ( "ethernet0", &offset ) != 0 ) ) {
00464                 return rc;
00465         }
00466 
00467         /* Fetch MAC address */
00468         if ( ( rc = fdt_mac ( offset, netdev ) ) != 0 )
00469                 return rc;
00470 
00471         DBGC ( smscusb, "SMSCUSB %p using FDT MAC %s\n",
00472                smscusb, eth_ntoa ( netdev->hw_addr ) );
00473         return 0;
00474 }
00475 
00476 /******************************************************************************
00477  *
00478  * MII access
00479  *
00480  ******************************************************************************
00481  */
00482 
00483 /**
00484  * Wait for MII to become idle
00485  *
00486  * @v smscusb           SMSC USB device
00487  * @ret rc              Return status code
00488  */
00489 static int smscusb_mii_wait ( struct smscusb_device *smscusb ) {
00490         unsigned int base = smscusb->mii_base;
00491         uint32_t mii_access;
00492         unsigned int i;
00493         int rc;
00494 
00495         /* Wait for MIIBZY to become clear */
00496         for ( i = 0 ; i < SMSCUSB_MII_MAX_WAIT_MS ; i++ ) {
00497 
00498                 /* Read MII_ACCESS and check MIIBZY */
00499                 if ( ( rc = smscusb_readl ( smscusb,
00500                                             ( base + SMSCUSB_MII_ACCESS ),
00501                                             &mii_access ) ) != 0 )
00502                         return rc;
00503                 if ( ! ( mii_access & SMSCUSB_MII_ACCESS_MIIBZY ) )
00504                         return 0;
00505 
00506                 /* Delay */
00507                 mdelay ( 1 );
00508         }
00509 
00510         DBGC ( smscusb, "SMSCUSB %p timed out waiting for MII\n",
00511                smscusb );
00512         return -ETIMEDOUT;
00513 }
00514 
00515 /**
00516  * Read from MII register
00517  *
00518  * @v mdio              MII interface
00519  * @v phy               PHY address
00520  * @v reg               Register address
00521  * @ret value           Data read, or negative error
00522  */
00523 static int smscusb_mii_read ( struct mii_interface *mdio,
00524                               unsigned int phy __unused, unsigned int reg ) {
00525         struct smscusb_device *smscusb =
00526                 container_of ( mdio, struct smscusb_device, mdio );
00527         unsigned int base = smscusb->mii_base;
00528         uint32_t mii_access;
00529         uint32_t mii_data;
00530         int rc;
00531 
00532         /* Wait for MII to become idle */
00533         if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
00534                 return rc;
00535 
00536         /* Initiate read command */
00537         mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
00538                        SMSCUSB_MII_ACCESS_MIIRINDA ( reg ) |
00539                        SMSCUSB_MII_ACCESS_MIIBZY );
00540         if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
00541                                      mii_access ) ) != 0 )
00542                 return rc;
00543 
00544         /* Wait for command to complete */
00545         if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
00546                 return rc;
00547 
00548         /* Read MII data */
00549         if ( ( rc = smscusb_readl ( smscusb, ( base + SMSCUSB_MII_DATA ),
00550                                     &mii_data ) ) != 0 )
00551                 return rc;
00552 
00553         return SMSCUSB_MII_DATA_GET ( mii_data );
00554 }
00555 
00556 /**
00557  * Write to MII register
00558  *
00559  * @v mdio              MII interface
00560  * @v phy               PHY address
00561  * @v reg               Register address
00562  * @v data              Data to write
00563  * @ret rc              Return status code
00564  */
00565 static int smscusb_mii_write ( struct mii_interface *mdio,
00566                                unsigned int phy __unused, unsigned int reg,
00567                                unsigned int data ) {
00568         struct smscusb_device *smscusb =
00569                 container_of ( mdio, struct smscusb_device, mdio );
00570         unsigned int base = smscusb->mii_base;
00571         uint32_t mii_access;
00572         uint32_t mii_data;
00573         int rc;
00574 
00575         /* Wait for MII to become idle */
00576         if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
00577                 return rc;
00578 
00579         /* Write MII data */
00580         mii_data = SMSCUSB_MII_DATA_SET ( data );
00581         if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_DATA ),
00582                                      mii_data ) ) != 0 )
00583                 return rc;
00584 
00585         /* Initiate write command */
00586         mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
00587                        SMSCUSB_MII_ACCESS_MIIRINDA ( reg ) |
00588                        SMSCUSB_MII_ACCESS_MIIWNR |
00589                        SMSCUSB_MII_ACCESS_MIIBZY );
00590         if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
00591                                      mii_access ) ) != 0 )
00592                 return rc;
00593 
00594         /* Wait for command to complete */
00595         if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
00596                 return rc;
00597 
00598         return 0;
00599 }
00600 
00601 /** MII operations */
00602 struct mii_operations smscusb_mii_operations = {
00603         .read = smscusb_mii_read,
00604         .write = smscusb_mii_write,
00605 };
00606 
00607 /**
00608  * Check link status
00609  *
00610  * @v smscusb           SMSC USB device
00611  * @ret rc              Return status code
00612  */
00613 int smscusb_mii_check_link ( struct smscusb_device *smscusb ) {
00614         struct net_device *netdev = smscusb->netdev;
00615         int intr;
00616         int rc;
00617 
00618         /* Read PHY interrupt source */
00619         intr = mii_read ( &smscusb->mii, smscusb->phy_source );
00620         if ( intr < 0 ) {
00621                 rc = intr;
00622                 DBGC ( smscusb, "SMSCUSB %p could not get PHY interrupt "
00623                        "source: %s\n", smscusb, strerror ( rc ) );
00624                 return rc;
00625         }
00626 
00627         /* Acknowledge PHY interrupt */
00628         if ( ( rc = mii_write ( &smscusb->mii, smscusb->phy_source,
00629                                 intr ) ) != 0 ) {
00630                 DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY "
00631                        "interrupt: %s\n", smscusb, strerror ( rc ) );
00632                 return rc;
00633         }
00634 
00635         /* Check link status */
00636         if ( ( rc = mii_check_link ( &smscusb->mii, netdev ) ) != 0 ) {
00637                 DBGC ( smscusb, "SMSCUSB %p could not check link: %s\n",
00638                        smscusb, strerror ( rc ) );
00639                 return rc;
00640         }
00641 
00642         DBGC ( smscusb, "SMSCUSB %p link %s (intr %#04x)\n",
00643                smscusb, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr );
00644         return 0;
00645 }
00646 
00647 /**
00648  * Enable PHY interrupts and update link status
00649  *
00650  * @v smscusb           SMSC USB device
00651  * @v phy_mask          PHY interrupt mask register
00652  * @v intrs             PHY interrupts to enable
00653  * @ret rc              Return status code
00654  */
00655 int smscusb_mii_open ( struct smscusb_device *smscusb,
00656                        unsigned int phy_mask, unsigned int intrs ) {
00657         int rc;
00658 
00659         /* Enable PHY interrupts */
00660         if ( ( rc = mii_write ( &smscusb->mii, phy_mask, intrs ) ) != 0 ) {
00661                 DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt "
00662                        "mask: %s\n", smscusb, strerror ( rc ) );
00663                 return rc;
00664         }
00665 
00666         /* Update link status */
00667         smscusb_mii_check_link ( smscusb );
00668 
00669         return 0;
00670 }
00671 
00672 /******************************************************************************
00673  *
00674  * Receive filtering
00675  *
00676  ******************************************************************************
00677  */
00678 
00679 /**
00680  * Set receive address
00681  *
00682  * @v smscusb           SMSC USB device
00683  * @v addr_base         Receive address register base
00684  * @ret rc              Return status code
00685  */
00686 int smscusb_set_address ( struct smscusb_device *smscusb,
00687                           unsigned int addr_base ) {
00688         struct net_device *netdev = smscusb->netdev;
00689         union smscusb_mac mac;
00690         int rc;
00691 
00692         /* Copy MAC address */
00693         memset ( &mac, 0, sizeof ( mac ) );
00694         memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
00695 
00696         /* Write MAC address high register */
00697         if ( ( rc = smscusb_raw_writel ( smscusb,
00698                                          ( addr_base + SMSCUSB_RX_ADDRH ),
00699                                          mac.addr.h ) ) != 0 )
00700                 return rc;
00701 
00702         /* Write MAC address low register */
00703         if ( ( rc = smscusb_raw_writel ( smscusb,
00704                                          ( addr_base + SMSCUSB_RX_ADDRL ),
00705                                          mac.addr.l ) ) != 0 )
00706                 return rc;
00707 
00708         return 0;
00709 }
00710 
00711 /**
00712  * Set receive filter
00713  *
00714  * @v smscusb           SMSC USB device
00715  * @v filt_base         Receive filter register base
00716  * @ret rc              Return status code
00717  */
00718 int smscusb_set_filter ( struct smscusb_device *smscusb,
00719                          unsigned int filt_base ) {
00720         struct net_device *netdev = smscusb->netdev;
00721         union smscusb_mac mac;
00722         int rc;
00723 
00724         /* Copy MAC address */
00725         memset ( &mac, 0, sizeof ( mac ) );
00726         memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
00727         mac.addr.h |= cpu_to_le32 ( SMSCUSB_ADDR_FILTH_VALID );
00728 
00729         /* Write MAC address perfect filter high register */
00730         if ( ( rc = smscusb_raw_writel ( smscusb,
00731                                          ( filt_base + SMSCUSB_ADDR_FILTH(0) ),
00732                                          mac.addr.h ) ) != 0 )
00733                 return rc;
00734 
00735         /* Write MAC address perfect filter low register */
00736         if ( ( rc = smscusb_raw_writel ( smscusb,
00737                                          ( filt_base + SMSCUSB_ADDR_FILTL(0) ),
00738                                          mac.addr.l ) ) != 0 )
00739                 return rc;
00740 
00741         return 0;
00742 }
00743 
00744 /******************************************************************************
00745  *
00746  * Endpoint operations
00747  *
00748  ******************************************************************************
00749  */
00750 
00751 /**
00752  * Complete interrupt transfer
00753  *
00754  * @v ep                USB endpoint
00755  * @v iobuf             I/O buffer
00756  * @v rc                Completion status code
00757  */
00758 static void smscusb_intr_complete ( struct usb_endpoint *ep,
00759                                     struct io_buffer *iobuf, int rc ) {
00760         struct smscusb_device *smscusb =
00761                 container_of ( ep, struct smscusb_device, usbnet.intr );
00762         struct net_device *netdev = smscusb->netdev;
00763         struct smscusb_interrupt *intr;
00764 
00765         /* Profile completions */
00766         profile_start ( &smscusb_intr_profiler );
00767 
00768         /* Ignore packets cancelled when the endpoint closes */
00769         if ( ! ep->open )
00770                 goto done;
00771 
00772         /* Record USB errors against the network device */
00773         if ( rc != 0 ) {
00774                 DBGC ( smscusb, "SMSCUSB %p interrupt failed: %s\n",
00775                        smscusb, strerror ( rc ) );
00776                 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
00777                 netdev_rx_err ( netdev, NULL, rc );
00778                 goto done;
00779         }
00780 
00781         /* Extract interrupt data */
00782         if ( iob_len ( iobuf ) != sizeof ( *intr ) ) {
00783                 DBGC ( smscusb, "SMSCUSB %p malformed interrupt\n",
00784                        smscusb );
00785                 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
00786                 netdev_rx_err ( netdev, NULL, rc );
00787                 goto done;
00788         }
00789         intr = iobuf->data;
00790 
00791         /* Record interrupt status */
00792         smscusb->int_sts = le32_to_cpu ( intr->int_sts );
00793         profile_stop ( &smscusb_intr_profiler );
00794 
00795  done:
00796         /* Free I/O buffer */
00797         free_iob ( iobuf );
00798 }
00799 
00800 /** Interrupt endpoint operations */
00801 struct usb_endpoint_driver_operations smscusb_intr_operations = {
00802         .complete = smscusb_intr_complete,
00803 };
00804 
00805 /**
00806  * Complete bulk OUT transfer
00807  *
00808  * @v ep                USB endpoint
00809  * @v iobuf             I/O buffer
00810  * @v rc                Completion status code
00811  */
00812 static void smscusb_out_complete ( struct usb_endpoint *ep,
00813                                    struct io_buffer *iobuf, int rc ) {
00814         struct smscusb_device *smscusb =
00815                 container_of ( ep, struct smscusb_device, usbnet.out );
00816         struct net_device *netdev = smscusb->netdev;
00817 
00818         /* Report TX completion */
00819         netdev_tx_complete_err ( netdev, iobuf, rc );
00820 }
00821 
00822 /** Bulk OUT endpoint operations */
00823 struct usb_endpoint_driver_operations smscusb_out_operations = {
00824         .complete = smscusb_out_complete,
00825 };