iPXE
dm96xx.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 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 <unistd.h>
00028 #include <errno.h>
00029 #include <ipxe/ethernet.h>
00030 #include <ipxe/usb.h>
00031 #include <ipxe/usbnet.h>
00032 #include "dm96xx.h"
00033 
00034 /** @file
00035  *
00036  * Davicom DM96xx USB Ethernet driver
00037  *
00038  */
00039 
00040 /******************************************************************************
00041  *
00042  * Register operations
00043  *
00044  ******************************************************************************
00045  */
00046 
00047 /**
00048  * Reset device
00049  *
00050  * @v dm96xx            DM96xx device
00051  * @ret rc              Return status code
00052  */
00053 static int dm96xx_reset ( struct dm96xx_device *dm96xx ) {
00054         int ncr;
00055         int rc;
00056 
00057         /* Reset device */
00058         if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_NCR,
00059                                             DM96XX_NCR_RST ) ) != 0 ) {
00060                 DBGC ( dm96xx, "DM96XX %p could not reset: %s\n",
00061                        dm96xx, strerror ( rc ) );
00062                 return rc;
00063         }
00064 
00065         /* Wait for reset to complete */
00066         udelay ( DM96XX_RESET_DELAY_US );
00067 
00068         /* Check that reset has completed */
00069         ncr = dm96xx_read_register ( dm96xx, DM96XX_NCR );
00070         if ( ncr < 0 ) {
00071                 rc = ncr;
00072                 DBGC ( dm96xx, "DM96XX %p failed to reset: %s\n",
00073                        dm96xx, strerror ( rc ) );
00074                 return rc;
00075         }
00076         if ( ncr & DM96XX_NCR_RST ) {
00077                 DBGC ( dm96xx, "DM96XX %p failed to reset (NCR=%#02x)\n",
00078                        dm96xx, ncr );
00079                 return -EIO;
00080         }
00081 
00082         return 0;
00083 }
00084 
00085 /**
00086  * Read MAC address
00087  *
00088  * @v dm96xx            DM96xx device
00089  * @v mac               MAC address to fill in
00090  * @ret rc              Return status code
00091  */
00092 static int dm96xx_read_mac ( struct dm96xx_device *dm96xx, uint8_t *mac ) {
00093         int rc;
00094 
00095         /* Read MAC address */
00096         if ( ( rc = dm96xx_read_registers ( dm96xx, DM96XX_PAR, mac,
00097                                             ETH_ALEN ) ) != 0 ) {
00098                 DBGC ( dm96xx, "DM96XX %p could not read MAC address: %s\n",
00099                        dm96xx, strerror ( rc ) );
00100                 return rc;
00101         }
00102 
00103         return 0;
00104 }
00105 
00106 /**
00107  * Write MAC address
00108  *
00109  * @v dm96xx            DM96xx device
00110  * @v mac               MAC address
00111  * @ret rc              Return status code
00112  */
00113 static int dm96xx_write_mac ( struct dm96xx_device *dm96xx, uint8_t *mac ) {
00114         int rc;
00115 
00116         /* Write MAC address */
00117         if ( ( rc = dm96xx_write_registers ( dm96xx, DM96XX_PAR, mac,
00118                                              ETH_ALEN ) ) != 0 ) {
00119                 DBGC ( dm96xx, "DM96XX %p could not write MAC address: %s\n",
00120                        dm96xx, strerror ( rc ) );
00121                 return rc;
00122         }
00123 
00124         return 0;
00125 }
00126 
00127 /**
00128  * Update link status based on network status register
00129  *
00130  * @v dm96xx            DM96xx device
00131  * @v nsr               Network status register
00132  */
00133 static void dm96xx_link_nsr ( struct dm96xx_device *dm96xx, unsigned int nsr ) {
00134         struct net_device *netdev = dm96xx->netdev;
00135 
00136         if ( nsr & DM96XX_NSR_LINKST ) {
00137                 if ( ! netdev_link_ok ( netdev ) )
00138                         netdev_link_up ( netdev );
00139         } else {
00140                 if ( netdev_link_ok ( netdev ) )
00141                         netdev_link_down ( netdev );
00142         }
00143 }
00144 
00145 /**
00146  * Get link status
00147  *
00148  * @v dm96xx            DM96xx device
00149  * @ret rc              Return status code
00150  */
00151 static int dm96xx_check_link ( struct dm96xx_device *dm96xx ) {
00152         int nsr;
00153         int rc;
00154 
00155         /* Read network status register */
00156         nsr = dm96xx_read_register ( dm96xx, DM96XX_NSR );
00157         if ( nsr < 0 ) {
00158                 rc = nsr;
00159                 DBGC ( dm96xx, "DM96XX %p could not read network status: %s\n",
00160                        dm96xx, strerror ( rc ) );
00161                 return rc;
00162         }
00163 
00164         /* Update link status */
00165         dm96xx_link_nsr ( dm96xx, nsr );
00166 
00167         return 0;
00168 }
00169 
00170 /**
00171  * Set DM9601-compatible RX header mode
00172  *
00173  * @v dm96xx            DM96xx device
00174  * @ret rc              Return status code
00175  */
00176 static int dm96xx_rx_mode ( struct dm96xx_device *dm96xx ) {
00177         int chipr;
00178         int mode_ctl;
00179         int rc;
00180 
00181         /* Get chip revision */
00182         chipr = dm96xx_read_register ( dm96xx, DM96XX_CHIPR );
00183         if ( chipr < 0 ) {
00184                 rc = chipr;
00185                 DBGC ( dm96xx, "DM96XX %p could not read chip revision: %s\n",
00186                        dm96xx, strerror ( rc ) );
00187                 return rc;
00188         }
00189 
00190         /* Do nothing if device is a DM9601 anyway */
00191         if ( chipr == DM96XX_CHIPR_9601 )
00192                 return 0;
00193 
00194         /* Read current mode control */
00195         mode_ctl = dm96xx_read_register ( dm96xx, DM96XX_MODE_CTL );
00196         if ( mode_ctl < 0 ) {
00197                 rc = mode_ctl;
00198                 DBGC ( dm96xx, "DM96XX %p could not read mode control: %s\n",
00199                        dm96xx, strerror ( rc ) );
00200                 return rc;
00201         }
00202 
00203         /* Write mode control */
00204         mode_ctl &= ~DM96XX_MODE_CTL_MODE;
00205         if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_MODE_CTL,
00206                                             mode_ctl ) ) != 0 ) {
00207                 DBGC ( dm96xx, "DM96XX %p could not write mode control: %s\n",
00208                        dm96xx, strerror ( rc ) );
00209                 return rc;
00210         }
00211 
00212         return 0;
00213 }
00214 
00215 /******************************************************************************
00216  *
00217  * Endpoint operations
00218  *
00219  ******************************************************************************
00220  */
00221 
00222 /**
00223  * Complete interrupt transfer
00224  *
00225  * @v ep                USB endpoint
00226  * @v iobuf             I/O buffer
00227  * @v rc                Completion status code
00228  */
00229 static void dm96xx_intr_complete ( struct usb_endpoint *ep,
00230                                    struct io_buffer *iobuf, int rc ) {
00231         struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
00232                                                       usbnet.intr );
00233         struct net_device *netdev = dm96xx->netdev;
00234         struct dm96xx_interrupt *intr;
00235         size_t len = iob_len ( iobuf );
00236 
00237         /* Ignore packets cancelled when the endpoint closes */
00238         if ( ! ep->open )
00239                 goto done;
00240 
00241         /* Record USB errors against the network device */
00242         if ( rc != 0 ) {
00243                 DBGC ( dm96xx, "DM96XX %p interrupt failed: %s\n",
00244                        dm96xx, strerror ( rc ) );
00245                 DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
00246                 netdev_rx_err ( netdev, NULL, rc );
00247                 goto done;
00248         }
00249 
00250         /* Extract message header */
00251         if ( len < sizeof ( *intr ) ) {
00252                 DBGC ( dm96xx, "DM96XX %p underlength interrupt:\n", dm96xx );
00253                 DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
00254                 netdev_rx_err ( netdev, NULL, -EINVAL );
00255                 goto done;
00256         }
00257         intr = iobuf->data;
00258 
00259         /* Update link status */
00260         dm96xx_link_nsr ( dm96xx, intr->nsr );
00261 
00262  done:
00263         /* Free I/O buffer */
00264         free_iob ( iobuf );
00265 }
00266 
00267 /** Interrupt endpoint operations */
00268 static struct usb_endpoint_driver_operations dm96xx_intr_operations = {
00269         .complete = dm96xx_intr_complete,
00270 };
00271 
00272 /**
00273  * Complete bulk IN transfer
00274  *
00275  * @v ep                USB endpoint
00276  * @v iobuf             I/O buffer
00277  * @v rc                Completion status code
00278  */
00279 static void dm96xx_in_complete ( struct usb_endpoint *ep,
00280                                  struct io_buffer *iobuf, int rc ) {
00281         struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
00282                                                       usbnet.in );
00283         struct net_device *netdev = dm96xx->netdev;
00284         struct dm96xx_rx_header *header;
00285 
00286         /* Ignore packets cancelled when the endpoint closes */
00287         if ( ! ep->open ) {
00288                 free_iob ( iobuf );
00289                 return;
00290         }
00291 
00292         /* Record USB errors against the network device */
00293         if ( rc != 0 ) {
00294                 DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
00295                        dm96xx, strerror ( rc ) );
00296                 goto err;
00297         }
00298 
00299         /* Sanity check */
00300         if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
00301                 DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
00302                 DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
00303                 rc = -EINVAL;
00304                 goto err;
00305         }
00306 
00307         /* Strip header and CRC */
00308         header = iobuf->data;
00309         iob_pull ( iobuf, sizeof ( *header ) );
00310         iob_unput ( iobuf, 4 /* CRC */ );
00311 
00312         /* Check status */
00313         if ( header->rsr & ~DM96XX_RSR_MF ) {
00314                 DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
00315                        dm96xx, header->rsr );
00316                 DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
00317                 rc = -EIO;
00318                 goto err;
00319         }
00320 
00321         /* Hand off to network stack */
00322         netdev_rx ( netdev, iob_disown ( iobuf ) );
00323         return;
00324 
00325  err:
00326         /* Hand off to network stack */
00327         netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
00328 }
00329 
00330 /** Bulk IN endpoint operations */
00331 static struct usb_endpoint_driver_operations dm96xx_in_operations = {
00332         .complete = dm96xx_in_complete,
00333 };
00334 
00335 /**
00336  * Transmit packet
00337  *
00338  * @v dm96xx            DM96xx device
00339  * @v iobuf             I/O buffer
00340  * @ret rc              Return status code
00341  */
00342 static int dm96xx_out_transmit ( struct dm96xx_device *dm96xx,
00343                                  struct io_buffer *iobuf ) {
00344         struct dm96xx_tx_header *header;
00345         size_t len = iob_len ( iobuf );
00346         int rc;
00347 
00348         /* Prepend header */
00349         if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *header ) ) ) != 0 )
00350                 return rc;
00351         header = iob_push ( iobuf, sizeof ( *header ) );
00352         header->len = cpu_to_le16 ( len );
00353 
00354         /* Enqueue I/O buffer */
00355         if ( ( rc = usb_stream ( &dm96xx->usbnet.out, iobuf, 0 ) ) != 0 )
00356                 return rc;
00357 
00358         return 0;
00359 }
00360 
00361 /**
00362  * Complete bulk OUT transfer
00363  *
00364  * @v ep                USB endpoint
00365  * @v iobuf             I/O buffer
00366  * @v rc                Completion status code
00367  */
00368 static void dm96xx_out_complete ( struct usb_endpoint *ep,
00369                                   struct io_buffer *iobuf, int rc ) {
00370         struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
00371                                                       usbnet.out );
00372         struct net_device *netdev = dm96xx->netdev;
00373 
00374         /* Report TX completion */
00375         netdev_tx_complete_err ( netdev, iobuf, rc );
00376 }
00377 
00378 /** Bulk OUT endpoint operations */
00379 static struct usb_endpoint_driver_operations dm96xx_out_operations = {
00380         .complete = dm96xx_out_complete,
00381 };
00382 
00383 /******************************************************************************
00384  *
00385  * Network device interface
00386  *
00387  ******************************************************************************
00388  */
00389 
00390 /**
00391  * Open network device
00392  *
00393  * @v netdev            Network device
00394  * @ret rc              Return status code
00395  */
00396 static int dm96xx_open ( struct net_device *netdev ) {
00397         struct dm96xx_device *dm96xx = netdev->priv;
00398         unsigned int rcr;
00399         int rc;
00400 
00401         /* Set DM9601-compatible RX header mode */
00402         if ( ( rc = dm96xx_rx_mode ( dm96xx ) ) != 0 )
00403                 goto err_rx_mode;
00404 
00405         /* Write MAC address */
00406         if ( ( rc = dm96xx_write_mac ( dm96xx, netdev->ll_addr ) ) != 0 )
00407                 goto err_write_mac;
00408 
00409         /* Open USB network device */
00410         if ( ( rc = usbnet_open ( &dm96xx->usbnet ) ) != 0 ) {
00411                 DBGC ( dm96xx, "DM96XX %p could not open: %s\n",
00412                        dm96xx, strerror ( rc ) );
00413                 goto err_open;
00414         }
00415 
00416         /* Set receive filters */
00417         rcr = ( DM96XX_RCR_ALL | DM96XX_RCR_RUNT | DM96XX_RCR_PRMSC |
00418                 DM96XX_RCR_RXEN );
00419         if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_RCR, rcr ) ) != 0 ) {
00420                 DBGC ( dm96xx, "DM96XX %p could not write receive filters: "
00421                        "%s\n", dm96xx, strerror ( rc ) );
00422                 goto err_write_rcr;
00423         }
00424 
00425         /* Update link status */
00426         if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
00427                 goto err_check_link;
00428 
00429         return 0;
00430 
00431  err_check_link:
00432  err_write_rcr:
00433         usbnet_close ( &dm96xx->usbnet );
00434  err_open:
00435  err_write_mac:
00436  err_rx_mode:
00437         return rc;
00438 }
00439 
00440 /**
00441  * Close network device
00442  *
00443  * @v netdev            Network device
00444  */
00445 static void dm96xx_close ( struct net_device *netdev ) {
00446         struct dm96xx_device *dm96xx = netdev->priv;
00447 
00448         /* Close USB network device */
00449         usbnet_close ( &dm96xx->usbnet );
00450 
00451         /* Reset device */
00452         dm96xx_reset ( dm96xx );
00453 }
00454 
00455 /**
00456  * Transmit packet
00457  *
00458  * @v netdev            Network device
00459  * @v iobuf             I/O buffer
00460  * @ret rc              Return status code
00461  */
00462 static int dm96xx_transmit ( struct net_device *netdev,
00463                              struct io_buffer *iobuf ) {
00464         struct dm96xx_device *dm96xx = netdev->priv;
00465         int rc;
00466 
00467         /* Transmit packet */
00468         if ( ( rc = dm96xx_out_transmit ( dm96xx, iobuf ) ) != 0 )
00469                 return rc;
00470 
00471         return 0;
00472 }
00473 
00474 /**
00475  * Poll for completed and received packets
00476  *
00477  * @v netdev            Network device
00478  */
00479 static void dm96xx_poll ( struct net_device *netdev ) {
00480         struct dm96xx_device *dm96xx = netdev->priv;
00481         int rc;
00482 
00483         /* Poll USB bus */
00484         usb_poll ( dm96xx->bus );
00485 
00486         /* Refill endpoints */
00487         if ( ( rc = usbnet_refill ( &dm96xx->usbnet ) ) != 0 )
00488                 netdev_rx_err ( netdev, NULL, rc );
00489 }
00490 
00491 /** DM96xx network device operations */
00492 static struct net_device_operations dm96xx_operations = {
00493         .open           = dm96xx_open,
00494         .close          = dm96xx_close,
00495         .transmit       = dm96xx_transmit,
00496         .poll           = dm96xx_poll,
00497 };
00498 
00499 /******************************************************************************
00500  *
00501  * USB interface
00502  *
00503  ******************************************************************************
00504  */
00505 
00506 /**
00507  * Probe device
00508  *
00509  * @v func              USB function
00510  * @v config            Configuration descriptor
00511  * @ret rc              Return status code
00512  */
00513 static int dm96xx_probe ( struct usb_function *func,
00514                        struct usb_configuration_descriptor *config ) {
00515         struct usb_device *usb = func->usb;
00516         struct net_device *netdev;
00517         struct dm96xx_device *dm96xx;
00518         int rc;
00519 
00520         /* Allocate and initialise structure */
00521         netdev = alloc_etherdev ( sizeof ( *dm96xx ) );
00522         if ( ! netdev ) {
00523                 rc = -ENOMEM;
00524                 goto err_alloc;
00525         }
00526         netdev_init ( netdev, &dm96xx_operations );
00527         netdev->dev = &func->dev;
00528         dm96xx = netdev->priv;
00529         memset ( dm96xx, 0, sizeof ( *dm96xx ) );
00530         dm96xx->usb = usb;
00531         dm96xx->bus = usb->port->hub->bus;
00532         dm96xx->netdev = netdev;
00533         usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations,
00534                       &dm96xx_in_operations, &dm96xx_out_operations );
00535         usb_refill_init ( &dm96xx->usbnet.intr, 0, 0, DM96XX_INTR_MAX_FILL );
00536         usb_refill_init ( &dm96xx->usbnet.in, 0, DM96XX_IN_MTU,
00537                           DM96XX_IN_MAX_FILL );
00538         DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name );
00539 
00540         /* Describe USB network device */
00541         if ( ( rc = usbnet_describe ( &dm96xx->usbnet, config ) ) != 0 ) {
00542                 DBGC ( dm96xx, "DM96XX %p could not describe: %s\n",
00543                        dm96xx, strerror ( rc ) );
00544                 goto err_describe;
00545         }
00546 
00547         /* Reset device */
00548         if ( ( rc = dm96xx_reset ( dm96xx ) ) != 0 )
00549                 goto err_reset;
00550 
00551         /* Read MAC address */
00552         if ( ( rc = dm96xx_read_mac ( dm96xx, netdev->hw_addr ) ) != 0 )
00553                 goto err_read_mac;
00554 
00555         /* Get initial link status */
00556         if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
00557                 goto err_check_link;
00558 
00559         /* Register network device */
00560         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00561                 goto err_register;
00562 
00563         usb_func_set_drvdata ( func, netdev );
00564         return 0;
00565 
00566         unregister_netdev ( netdev );
00567  err_register:
00568  err_check_link:
00569  err_read_mac:
00570  err_reset:
00571  err_describe:
00572         netdev_nullify ( netdev );
00573         netdev_put ( netdev );
00574  err_alloc:
00575         return rc;
00576 }
00577 
00578 /**
00579  * Remove device
00580  *
00581  * @v func              USB function
00582  */
00583 static void dm96xx_remove ( struct usb_function *func ) {
00584         struct net_device *netdev = usb_func_get_drvdata ( func );
00585 
00586         unregister_netdev ( netdev );
00587         netdev_nullify ( netdev );
00588         netdev_put ( netdev );
00589 }
00590 
00591 /** DM96xx device IDs */
00592 static struct usb_device_id dm96xx_ids[] = {
00593         {
00594                 .name = "dm9601-corega",
00595                 .vendor = 0x07aa,
00596                 .product = 0x9601,
00597         },
00598         {
00599                 .name = "dm9601",
00600                 .vendor = 0x0a46,
00601                 .product = 0x9601,
00602         },
00603         {
00604                 .name = "zt6688",
00605                 .vendor = 0x0a46,
00606                 .product = 0x6688,
00607         },
00608         {
00609                 .name = "st268",
00610                 .vendor = 0x0a46,
00611                 .product = 0x0268,
00612         },
00613         {
00614                 .name = "adm8515",
00615                 .vendor = 0x0a46,
00616                 .product = 0x8515,
00617         },
00618         {
00619                 .name = "dm9601-hirose",
00620                 .vendor = 0x0a47,
00621                 .product = 0x9601,
00622         },
00623         {
00624                 .name = "dm9601-8101",
00625                 .vendor = 0x0fe6,
00626                 .product = 0x8101,
00627         },
00628         {
00629                 .name = "dm9601-9700",
00630                 .vendor = 0x0fe6,
00631                 .product = 0x9700,
00632         },
00633         {
00634                 .name = "dm9000e",
00635                 .vendor = 0x0a46,
00636                 .product = 0x9000,
00637         },
00638         {
00639                 .name = "dm9620",
00640                 .vendor = 0x0a46,
00641                 .product = 0x9620,
00642         },
00643         {
00644                 .name = "dm9621A",
00645                 .vendor = 0x0a46,
00646                 .product = 0x9621,
00647         },
00648         {
00649                 .name = "dm9622",
00650                 .vendor = 0x0a46,
00651                 .product = 0x9622,
00652         },
00653         {
00654                 .name = "dm962Oa",
00655                 .vendor = 0x0a46,
00656                 .product = 0x0269,
00657         },
00658         {
00659                 .name = "dm9621a",
00660                 .vendor = 0x0a46,
00661                 .product = 0x1269,
00662         },
00663 };
00664 
00665 /** Davicom DM96xx driver */
00666 struct usb_driver dm96xx_driver __usb_driver = {
00667         .ids = dm96xx_ids,
00668         .id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ),
00669         .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
00670         .score = USB_SCORE_NORMAL,
00671         .probe = dm96xx_probe,
00672         .remove = dm96xx_remove,
00673 };