iPXE
axge.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2016 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 <unistd.h>
00029 #include <errno.h>
00030 #include <ipxe/netdevice.h>
00031 #include <ipxe/ethernet.h>
00032 #include <ipxe/if_ether.h>
00033 #include <ipxe/profile.h>
00034 #include <ipxe/usb.h>
00035 #include "axge.h"
00036 
00037 /** @file
00038  *
00039  * Asix 10/100/1000 USB Ethernet driver
00040  *
00041  * Large chunks of functionality are undocumented in the available
00042  * datasheets.  The gaps are deduced from combinations of the Linux
00043  * driver, the FreeBSD driver, and experimentation with the hardware.
00044  */
00045 
00046 /** Interrupt completion profiler */
00047 static struct profiler axge_intr_profiler __profiler =
00048         { .name = "axge.intr" };
00049 
00050 /** Bulk IN completion profiler */
00051 static struct profiler axge_in_profiler __profiler =
00052         { .name = "axge.in" };
00053 
00054 /** Bulk OUT profiler */
00055 static struct profiler axge_out_profiler __profiler =
00056         { .name = "axge.out" };
00057 
00058 /** Default bulk IN configuration
00059  *
00060  * The Linux and FreeBSD drivers have set of magic constants which are
00061  * chosen based on both the Ethernet and USB link speeds.
00062  *
00063  * Experimentation shows that setting the "timer" value to zero seems
00064  * to prevent the device from ever coalescing multiple packets into a
00065  * single bulk IN transfer.  This allows us to get away with using a
00066  * 2kB receive I/O buffer and a zerocopy receive path.
00067  */
00068 static struct axge_bulk_in_control axge_bicr = {
00069         .ctrl = 7,
00070         .timer = cpu_to_le16 ( 0 ),
00071         .size = 0,
00072         .ifg = 0,
00073 };
00074 
00075 /******************************************************************************
00076  *
00077  * Register access
00078  *
00079  ******************************************************************************
00080  */
00081 
00082 /**
00083  * Read register
00084  *
00085  * @v asix              AXGE device
00086  * @v offset            Register offset
00087  * @v data              Data buffer
00088  * @v len               Length of data
00089  * @ret rc              Return status code
00090  */
00091 static inline int axge_read_register ( struct axge_device *axge,
00092                                        unsigned int offset, void *data,
00093                                        size_t len ) {
00094 
00095         return usb_control ( axge->usb, AXGE_READ_MAC_REGISTER,
00096                              offset, len, data, len );
00097 }
00098 
00099 /**
00100  * Read one-byte register
00101  *
00102  * @v asix              AXGE device
00103  * @v offset            Register offset
00104  * @v value             Value to fill in
00105  * @ret rc              Return status code
00106  */
00107 static inline int axge_read_byte ( struct axge_device *axge,
00108                                    unsigned int offset, uint8_t *value ) {
00109 
00110         return axge_read_register ( axge, offset, value, sizeof ( *value ) );
00111 }
00112 
00113 /**
00114  * Read two-byte register
00115  *
00116  * @v asix              AXGE device
00117  * @v offset            Register offset
00118  * @v value             Value to fill in
00119  * @ret rc              Return status code
00120  */
00121 static inline int axge_read_word ( struct axge_device *axge,
00122                                    unsigned int offset, uint16_t *value ) {
00123 
00124         return axge_read_register ( axge, offset, value, sizeof ( *value ) );
00125 }
00126 
00127 /**
00128  * Read four-byte register
00129  *
00130  * @v asix              AXGE device
00131  * @v offset            Register offset
00132  * @v value             Value to fill in
00133  * @ret rc              Return status code
00134  */
00135 static inline int axge_read_dword ( struct axge_device *axge,
00136                                     unsigned int offset, uint32_t *value ) {
00137 
00138         return axge_read_register ( axge, offset, value, sizeof ( *value ) );
00139 }
00140 
00141 /**
00142  * Write register
00143  *
00144  * @v asix              AXGE device
00145  * @v offset            Register offset
00146  * @v data              Data buffer
00147  * @v len               Length of data
00148  * @ret rc              Return status code
00149  */
00150 static inline int axge_write_register ( struct axge_device *axge,
00151                                         unsigned int offset, void *data,
00152                                         size_t len ) {
00153 
00154         return usb_control ( axge->usb, AXGE_WRITE_MAC_REGISTER,
00155                              offset, len, data, len );
00156 }
00157 
00158 /**
00159  * Write one-byte register
00160  *
00161  * @v asix              AXGE device
00162  * @v offset            Register offset
00163  * @v value             Value
00164  * @ret rc              Return status code
00165  */
00166 static inline int axge_write_byte ( struct axge_device *axge,
00167                                     unsigned int offset, uint8_t value ) {
00168 
00169         return axge_write_register ( axge, offset, &value, sizeof ( value ));
00170 }
00171 
00172 /**
00173  * Write two-byte register
00174  *
00175  * @v asix              AXGE device
00176  * @v offset            Register offset
00177  * @v value             Value
00178  * @ret rc              Return status code
00179  */
00180 static inline int axge_write_word ( struct axge_device *axge,
00181                                     unsigned int offset, uint16_t value ) {
00182 
00183         return axge_write_register ( axge, offset, &value, sizeof ( value ));
00184 }
00185 
00186 /**
00187  * Write one-byte register
00188  *
00189  * @v asix              AXGE device
00190  * @v offset            Register offset
00191  * @v value             Value
00192  * @ret rc              Return status code
00193  */
00194 static inline int axge_write_dword ( struct axge_device *axge,
00195                                      unsigned int offset, uint32_t value ) {
00196 
00197         return axge_write_register ( axge, offset, &value, sizeof ( value ));
00198 }
00199 
00200 /******************************************************************************
00201  *
00202  * Link status
00203  *
00204  ******************************************************************************
00205  */
00206 
00207 /**
00208  * Get link status
00209  *
00210  * @v asix              AXGE device
00211  * @ret rc              Return status code
00212  */
00213 static int axge_check_link ( struct axge_device *axge ) {
00214         struct net_device *netdev = axge->netdev;
00215         uint8_t plsr;
00216         int rc;
00217 
00218         /* Read physical link status register */
00219         if ( ( rc = axge_read_byte ( axge, AXGE_PLSR, &plsr ) ) != 0 ) {
00220                 DBGC ( axge, "AXGE %p could not read PLSR: %s\n",
00221                        axge, strerror ( rc ) );
00222                 return rc;
00223         }
00224 
00225         /* Update link status */
00226         if ( plsr & AXGE_PLSR_EPHY_ANY ) {
00227                 DBGC ( axge, "AXGE %p link up (PLSR %02x)\n", axge, plsr );
00228                 netdev_link_up ( netdev );
00229         } else {
00230                 DBGC ( axge, "AXGE %p link down (PLSR %02x)\n", axge, plsr );
00231                 netdev_link_down ( netdev );
00232         }
00233 
00234         return 0;
00235 }
00236 
00237 /******************************************************************************
00238  *
00239  * AXGE communications interface
00240  *
00241  ******************************************************************************
00242  */
00243 
00244 /**
00245  * Complete interrupt transfer
00246  *
00247  * @v ep                USB endpoint
00248  * @v iobuf             I/O buffer
00249  * @v rc                Completion status code
00250  */
00251 static void axge_intr_complete ( struct usb_endpoint *ep,
00252                                  struct io_buffer *iobuf, int rc ) {
00253         struct axge_device *axge = container_of ( ep, struct axge_device,
00254                                                   usbnet.intr );
00255         struct net_device *netdev = axge->netdev;
00256         struct axge_interrupt *intr;
00257         size_t len = iob_len ( iobuf );
00258         unsigned int link_ok;
00259 
00260         /* Profile completions */
00261         profile_start ( &axge_intr_profiler );
00262 
00263         /* Ignore packets cancelled when the endpoint closes */
00264         if ( ! ep->open )
00265                 goto ignore;
00266 
00267         /* Drop packets with errors */
00268         if ( rc != 0 ) {
00269                 DBGC ( axge, "AXGE %p interrupt failed: %s\n",
00270                        axge, strerror ( rc ) );
00271                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00272                 goto error;
00273         }
00274 
00275         /* Extract message header */
00276         if ( len < sizeof ( *intr ) ) {
00277                 DBGC ( axge, "AXGE %p underlength interrupt:\n", axge );
00278                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00279                 rc = -EINVAL;
00280                 goto error;
00281         }
00282         intr = iobuf->data;
00283 
00284         /* Check magic signature */
00285         if ( intr->magic != cpu_to_le16 ( AXGE_INTR_MAGIC ) ) {
00286                 DBGC ( axge, "AXGE %p malformed interrupt:\n", axge );
00287                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00288                 rc = -EINVAL;
00289                 goto error;
00290         }
00291 
00292         /* Extract link status */
00293         link_ok = ( intr->link & cpu_to_le16 ( AXGE_INTR_LINK_PPLS ) );
00294         if ( link_ok && ! netdev_link_ok ( netdev ) ) {
00295                 DBGC ( axge, "AXGE %p link up\n", axge );
00296                 netdev_link_up ( netdev );
00297         } else if ( netdev_link_ok ( netdev ) && ! link_ok ) {
00298                 DBGC ( axge, "AXGE %p link down\n", axge );
00299                 netdev_link_down ( netdev );
00300         }
00301 
00302         /* Free I/O buffer */
00303         free_iob ( iobuf );
00304         profile_stop ( &axge_intr_profiler );
00305 
00306         return;
00307 
00308  error:
00309         netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
00310  ignore:
00311         free_iob ( iobuf );
00312         return;
00313 }
00314 
00315 /** Interrupt endpoint operations */
00316 static struct usb_endpoint_driver_operations axge_intr_operations = {
00317         .complete = axge_intr_complete,
00318 };
00319 
00320 /******************************************************************************
00321  *
00322  * AXGE data interface
00323  *
00324  ******************************************************************************
00325  */
00326 
00327 /**
00328  * Complete bulk IN transfer
00329  *
00330  * @v ep                USB endpoint
00331  * @v iobuf             I/O buffer
00332  * @v rc                Completion status code
00333  */
00334 static void axge_in_complete ( struct usb_endpoint *ep,
00335                                struct io_buffer *iobuf, int rc ) {
00336         struct axge_device *axge = container_of ( ep, struct axge_device,
00337                                                   usbnet.in );
00338         struct net_device *netdev = axge->netdev;
00339         struct axge_rx_footer *ftr;
00340         struct axge_rx_descriptor *desc;
00341         struct io_buffer *pkt;
00342         unsigned int count;
00343         unsigned int offset;
00344         size_t len;
00345         size_t padded_len;
00346 
00347         /* Profile receive completions */
00348         profile_start ( &axge_in_profiler );
00349 
00350         /* Ignore packets cancelled when the endpoint closes */
00351         if ( ! ep->open )
00352                 goto ignore;
00353 
00354         /* Record USB errors against the network device */
00355         if ( rc != 0 ) {
00356                 DBGC ( axge, "AXGE %p bulk IN failed: %s\n",
00357                        axge, strerror ( rc ) );
00358                 goto error;
00359         }
00360 
00361         /* Sanity check */
00362         if ( iob_len ( iobuf ) < sizeof ( *ftr ) ) {
00363                 DBGC ( axge, "AXGE %p underlength bulk IN:\n", axge );
00364                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00365                 rc = -EINVAL;
00366                 goto error;
00367         }
00368 
00369         /* Parse ftr, strip ftr and descriptors */
00370         iob_unput ( iobuf, sizeof ( *ftr ) );
00371         ftr = ( iobuf->data + iob_len ( iobuf ) );
00372         count = le16_to_cpu ( ftr->count );
00373         if ( count == 0 ) {
00374                 DBGC ( axge, "AXGE %p zero-packet bulk IN:\n", axge );
00375                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00376                 goto ignore;
00377         }
00378         offset = le16_to_cpu ( ftr->offset );
00379         if ( ( iob_len ( iobuf ) < offset ) ||
00380              ( ( iob_len ( iobuf ) - offset ) < ( count * sizeof ( *desc ) ) )){
00381                 DBGC ( axge, "AXGE %p malformed bulk IN footer:\n", axge );
00382                 DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00383                 rc = -EINVAL;
00384                 goto error;
00385         }
00386         desc = ( iobuf->data + offset );
00387         iob_unput ( iobuf, ( iob_len ( iobuf ) - offset ) );
00388 
00389         /* Process packets */
00390         for ( ; count-- ; desc++ ) {
00391 
00392                 /* Parse descriptor */
00393                 len = ( le16_to_cpu ( desc->len_flags ) & AXGE_RX_LEN_MASK );
00394                 padded_len = ( ( len + AXGE_RX_LEN_PAD_ALIGN - 1 ) &
00395                                ~( AXGE_RX_LEN_PAD_ALIGN - 1 ) );
00396                 if ( iob_len ( iobuf ) < padded_len ) {
00397                         DBGC ( axge, "AXGE %p malformed bulk IN descriptor:\n",
00398                                axge );
00399                         DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
00400                         rc = -EINVAL;
00401                         goto error;
00402                 }
00403 
00404                 /* Check for previous dropped packets */
00405                 if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_CRC_ERROR ) )
00406                         netdev_rx_err ( netdev, NULL, -EIO );
00407                 if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_DROP_ERROR ) )
00408                         netdev_rx_err ( netdev, NULL, -ENOBUFS );
00409 
00410                 /* Allocate new I/O buffer, if applicable */
00411                 if ( count ) {
00412 
00413                         /* More packets remain: allocate a new buffer */
00414                         pkt = alloc_iob ( AXGE_IN_RESERVE + len );
00415                         if ( ! pkt ) {
00416                                 /* Record error and continue */
00417                                 netdev_rx_err ( netdev, NULL, -ENOMEM );
00418                                 iob_pull ( iobuf, padded_len );
00419                                 continue;
00420                         }
00421                         iob_reserve ( pkt, AXGE_IN_RESERVE );
00422                         memcpy ( iob_put ( pkt, len ), iobuf->data, len );
00423                         iob_pull ( iobuf, padded_len );
00424 
00425                 } else {
00426 
00427                         /* This is the last (or only) packet: use this buffer */
00428                         iob_unput ( iobuf, ( padded_len - len ) );
00429                         pkt = iob_disown ( iobuf );
00430                 }
00431 
00432                 /* Hand off to network stack */
00433                 netdev_rx ( netdev, iob_disown ( pkt ) );
00434         }
00435 
00436         assert ( iobuf == NULL );
00437         profile_stop ( &axge_in_profiler );
00438         return;
00439 
00440  error:
00441         netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
00442  ignore:
00443         free_iob ( iobuf );
00444 }
00445 
00446 /** Bulk IN endpoint operations */
00447 static struct usb_endpoint_driver_operations axge_in_operations = {
00448         .complete = axge_in_complete,
00449 };
00450 
00451 /**
00452  * Transmit packet
00453  *
00454  * @v asix              AXGE device
00455  * @v iobuf             I/O buffer
00456  * @ret rc              Return status code
00457  */
00458 static int axge_out_transmit ( struct axge_device *axge,
00459                                struct io_buffer *iobuf ) {
00460         struct axge_tx_header *hdr;
00461         size_t len = iob_len ( iobuf );
00462         int rc;
00463 
00464         /* Profile transmissions */
00465         profile_start ( &axge_out_profiler );
00466 
00467         /* Prepend header */
00468         if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *hdr ) ) ) != 0 )
00469                 return rc;
00470         hdr = iob_push ( iobuf, sizeof ( *hdr ) );
00471         hdr->len = cpu_to_le32 ( len );
00472         hdr->wtf = 0;
00473 
00474         /* Enqueue I/O buffer */
00475         if ( ( rc = usb_stream ( &axge->usbnet.out, iobuf, 0 ) ) != 0 )
00476                 return rc;
00477 
00478         profile_stop ( &axge_out_profiler );
00479         return 0;
00480 }
00481 
00482 /**
00483  * Complete bulk OUT transfer
00484  *
00485  * @v ep                USB endpoint
00486  * @v iobuf             I/O buffer
00487  * @v rc                Completion status code
00488  */
00489 static void axge_out_complete ( struct usb_endpoint *ep,
00490                                 struct io_buffer *iobuf, int rc ) {
00491         struct axge_device *axge = container_of ( ep, struct axge_device,
00492                                                   usbnet.out );
00493         struct net_device *netdev = axge->netdev;
00494 
00495         /* Report TX completion */
00496         netdev_tx_complete_err ( netdev, iobuf, rc );
00497 }
00498 
00499 /** Bulk OUT endpoint operations */
00500 static struct usb_endpoint_driver_operations axge_out_operations = {
00501         .complete = axge_out_complete,
00502 };
00503 
00504 /******************************************************************************
00505  *
00506  * Network device interface
00507  *
00508  ******************************************************************************
00509  */
00510 
00511 /**
00512  * Open network device
00513  *
00514  * @v netdev            Network device
00515  * @ret rc              Return status code
00516  */
00517 static int axge_open ( struct net_device *netdev ) {
00518         struct axge_device *axge = netdev->priv;
00519         uint16_t rcr;
00520         int rc;
00521 
00522         /* Open USB network device */
00523         if ( ( rc = usbnet_open ( &axge->usbnet ) ) != 0 ) {
00524                 DBGC ( axge, "AXGE %p could not open: %s\n",
00525                        axge, strerror ( rc ) );
00526                 goto err_open;
00527         }
00528 
00529         /* Set MAC address */
00530         if ( ( rc = axge_write_register ( axge, AXGE_NIDR,
00531                                           netdev->ll_addr, ETH_ALEN ) ) !=0){
00532                 DBGC ( axge, "AXGE %p could not set MAC address: %s\n",
00533                        axge, strerror ( rc ) );
00534                 goto err_write_mac;
00535         }
00536 
00537         /* Enable receiver */
00538         rcr = cpu_to_le16 ( AXGE_RCR_PRO | AXGE_RCR_AMALL |
00539                             AXGE_RCR_AB | AXGE_RCR_SO );
00540         if ( ( rc = axge_write_word ( axge, AXGE_RCR, rcr ) ) != 0 ) {
00541                 DBGC ( axge, "AXGE %p could not write RCR: %s\n",
00542                        axge, strerror ( rc ) );
00543                 goto err_write_rcr;
00544         }
00545 
00546         /* Update link status */
00547         axge_check_link ( axge );
00548 
00549         return 0;
00550 
00551         axge_write_word ( axge, AXGE_RCR, 0 );
00552  err_write_rcr:
00553  err_write_mac:
00554         usbnet_close ( &axge->usbnet );
00555  err_open:
00556         return rc;
00557 }
00558 
00559 /**
00560  * Close network device
00561  *
00562  * @v netdev            Network device
00563  */
00564 static void axge_close ( struct net_device *netdev ) {
00565         struct axge_device *axge = netdev->priv;
00566 
00567         /* Disable receiver */
00568         axge_write_word ( axge, AXGE_RCR, 0 );
00569 
00570         /* Close USB network device */
00571         usbnet_close ( &axge->usbnet );
00572 }
00573 
00574 /**
00575  * Transmit packet
00576  *
00577  * @v netdev            Network device
00578  * @v iobuf             I/O buffer
00579  * @ret rc              Return status code
00580  */
00581 static int axge_transmit ( struct net_device *netdev,
00582                            struct io_buffer *iobuf ) {
00583         struct axge_device *axge = netdev->priv;
00584         int rc;
00585 
00586         /* Transmit packet */
00587         if ( ( rc = axge_out_transmit ( axge, iobuf ) ) != 0 )
00588                 return rc;
00589 
00590         return 0;
00591 }
00592 
00593 /**
00594  * Poll for completed and received packets
00595  *
00596  * @v netdev            Network device
00597  */
00598 static void axge_poll ( struct net_device *netdev ) {
00599         struct axge_device *axge = netdev->priv;
00600         int rc;
00601 
00602         /* Poll USB bus */
00603         usb_poll ( axge->bus );
00604 
00605         /* Refill endpoints */
00606         if ( ( rc = usbnet_refill ( &axge->usbnet ) ) != 0 )
00607                 netdev_rx_err ( netdev, NULL, rc );
00608 }
00609 
00610 /** AXGE network device operations */
00611 static struct net_device_operations axge_operations = {
00612         .open           = axge_open,
00613         .close          = axge_close,
00614         .transmit       = axge_transmit,
00615         .poll           = axge_poll,
00616 };
00617 
00618 /******************************************************************************
00619  *
00620  * USB interface
00621  *
00622  ******************************************************************************
00623  */
00624 
00625 /**
00626  * Probe device
00627  *
00628  * @v func              USB function
00629  * @v config            Configuration descriptor
00630  * @ret rc              Return status code
00631  */
00632 static int axge_probe ( struct usb_function *func,
00633                         struct usb_configuration_descriptor *config ) {
00634         struct usb_device *usb = func->usb;
00635         struct net_device *netdev;
00636         struct axge_device *axge;
00637         uint16_t epprcr;
00638         uint16_t msr;
00639         uint8_t csr;
00640         int rc;
00641 
00642         /* Allocate and initialise structure */
00643         netdev = alloc_etherdev ( sizeof ( *axge ) );
00644         if ( ! netdev ) {
00645                 rc = -ENOMEM;
00646                 goto err_alloc;
00647         }
00648         netdev_init ( netdev, &axge_operations );
00649         netdev->dev = &func->dev;
00650         axge = netdev->priv;
00651         memset ( axge, 0, sizeof ( *axge ) );
00652         axge->usb = usb;
00653         axge->bus = usb->port->hub->bus;
00654         axge->netdev = netdev;
00655         usbnet_init ( &axge->usbnet, func, &axge_intr_operations,
00656                       &axge_in_operations, &axge_out_operations );
00657         usb_refill_init ( &axge->usbnet.intr, 0, 0, AXGE_INTR_MAX_FILL );
00658         usb_refill_init ( &axge->usbnet.in, AXGE_IN_RESERVE,
00659                           AXGE_IN_MTU, AXGE_IN_MAX_FILL );
00660         DBGC ( axge, "AXGE %p on %s\n", axge, func->name );
00661 
00662         /* Describe USB network device */
00663         if ( ( rc = usbnet_describe ( &axge->usbnet, config ) ) != 0 ) {
00664                 DBGC ( axge, "AXGE %p could not describe: %s\n",
00665                        axge, strerror ( rc ) );
00666                 goto err_describe;
00667         }
00668 
00669         /* Fetch MAC address */
00670         if ( ( rc = axge_read_register ( axge, AXGE_NIDR, netdev->hw_addr,
00671                                          ETH_ALEN ) ) != 0 ) {
00672                 DBGC ( axge, "AXGE %p could not fetch MAC address: %s\n",
00673                        axge, strerror ( rc ) );
00674                 goto err_read_mac;
00675         }
00676 
00677         /* Power up PHY */
00678         if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, 0 ) ) != 0 ) {
00679                 DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n",
00680                        axge, strerror ( rc ) );
00681                 goto err_write_epprcr_off;
00682         }
00683         epprcr = cpu_to_le16 ( AXGE_EPPRCR_IPRL );
00684         if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, epprcr ) ) != 0){
00685                 DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n",
00686                        axge, strerror ( rc ) );
00687                 goto err_write_epprcr_on;
00688         }
00689         mdelay ( AXGE_EPPRCR_DELAY_MS );
00690 
00691         /* Select clocks */
00692         csr = ( AXGE_CSR_BCS | AXGE_CSR_ACS );
00693         if ( ( rc = axge_write_byte ( axge, AXGE_CSR, csr ) ) != 0){
00694                 DBGC ( axge, "AXGE %p could not write CSR: %s\n",
00695                        axge, strerror ( rc ) );
00696                 goto err_write_csr;
00697         }
00698         mdelay ( AXGE_CSR_DELAY_MS );
00699 
00700         /* Configure bulk IN pipeline */
00701         if ( ( rc = axge_write_register ( axge, AXGE_BICR, &axge_bicr,
00702                                           sizeof ( axge_bicr ) ) ) != 0 ){
00703                 DBGC ( axge, "AXGE %p could not write BICR: %s\n",
00704                        axge, strerror ( rc ) );
00705                 goto err_write_bicr;
00706         }
00707 
00708         /* Set medium status */
00709         msr = cpu_to_le16 ( AXGE_MSR_GM | AXGE_MSR_FD | AXGE_MSR_RFC |
00710                             AXGE_MSR_TFC | AXGE_MSR_RE );
00711         if ( ( rc = axge_write_word ( axge, AXGE_MSR, msr ) ) != 0 ) {
00712                 DBGC ( axge, "AXGE %p could not write MSR: %s\n",
00713                        axge, strerror ( rc ) );
00714                 goto err_write_msr;
00715         }
00716 
00717         /* Register network device */
00718         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00719                 goto err_register;
00720 
00721         /* Update link status */
00722         axge_check_link ( axge );
00723 
00724         usb_func_set_drvdata ( func, axge );
00725         return 0;
00726 
00727         unregister_netdev ( netdev );
00728  err_register:
00729  err_write_msr:
00730  err_write_bicr:
00731  err_write_csr:
00732  err_write_epprcr_on:
00733  err_write_epprcr_off:
00734  err_read_mac:
00735  err_describe:
00736         netdev_nullify ( netdev );
00737         netdev_put ( netdev );
00738  err_alloc:
00739         return rc;
00740 }
00741 
00742 /**
00743  * Remove device
00744  *
00745  * @v func              USB function
00746  */
00747 static void axge_remove ( struct usb_function *func ) {
00748         struct axge_device *axge = usb_func_get_drvdata ( func );
00749         struct net_device *netdev = axge->netdev;
00750 
00751         unregister_netdev ( netdev );
00752         netdev_nullify ( netdev );
00753         netdev_put ( netdev );
00754 }
00755 
00756 /** AXGE device IDs */
00757 static struct usb_device_id axge_ids[] = {
00758         {
00759                 .name = "ax88179",
00760                 .vendor = 0x0b95,
00761                 .product = 0x1790,
00762         },
00763         {
00764                 .name = "ax88178a",
00765                 .vendor = 0x0b95,
00766                 .product = 0x178a,
00767         },
00768         {
00769                 .name = "dub1312",
00770                 .vendor = 0x2001,
00771                 .product = 0x4a00,
00772         },
00773         {
00774                 .name = "axge-sitecom",
00775                 .vendor = 0x0df6,
00776                 .product = 0x0072,
00777         },
00778         {
00779                 .name = "axge-samsung",
00780                 .vendor = 0x04e8,
00781                 .product = 0xa100,
00782         },
00783         {
00784                 .name = "onelinkdock",
00785                 .vendor = 0x17ef,
00786                 .product = 0x304b,
00787         },
00788 };
00789 
00790 /** AXGE driver */
00791 struct usb_driver axge_driver __usb_driver = {
00792         .ids = axge_ids,
00793         .id_count = ( sizeof ( axge_ids ) / sizeof ( axge_ids[0] ) ),
00794         .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
00795         .score = USB_SCORE_NORMAL,
00796         .probe = axge_probe,
00797         .remove = axge_remove,
00798 };