iPXE
skeleton.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 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 <byteswap.h>
00031 #include <ipxe/netdevice.h>
00032 #include <ipxe/ethernet.h>
00033 #include <ipxe/if_ether.h>
00034 #include <ipxe/iobuf.h>
00035 #include <ipxe/malloc.h>
00036 #include <ipxe/pci.h>
00037 #include "skeleton.h"
00038 
00039 /** @file
00040  *
00041  * Skeleton network driver
00042  *
00043  */
00044 
00045 /******************************************************************************
00046  *
00047  * Device reset
00048  *
00049  ******************************************************************************
00050  */
00051 
00052 /**
00053  * Reset hardware
00054  *
00055  * @v skel              Skeleton device
00056  * @ret rc              Return status code
00057  */
00058 static int skeleton_reset ( struct skeleton_nic *skel ) {
00059 
00060         DBGC ( skel, "SKELETON %p does not yet support reset\n", skel );
00061         return -ENOTSUP;
00062 }
00063 
00064 /******************************************************************************
00065  *
00066  * Link state
00067  *
00068  ******************************************************************************
00069  */
00070 
00071 /**
00072  * Check link state
00073  *
00074  * @v netdev            Network device
00075  */
00076 static void skeleton_check_link ( struct net_device *netdev ) {
00077         struct skeleton_nic *skel = netdev->priv;
00078 
00079         DBGC ( skel, "SKELETON %p does not yet support link state\n", skel );
00080         netdev_link_err ( netdev, -ENOTSUP );
00081 }
00082 
00083 /******************************************************************************
00084  *
00085  * Network device interface
00086  *
00087  ******************************************************************************
00088  */
00089 
00090 /**
00091  * Open network device
00092  *
00093  * @v netdev            Network device
00094  * @ret rc              Return status code
00095  */
00096 static int skeleton_open ( struct net_device *netdev ) {
00097         struct skeleton_nic *skel = netdev->priv;
00098 
00099         DBGC ( skel, "SKELETON %p does not yet support open\n", skel );
00100         return -ENOTSUP;
00101 }
00102 
00103 /**
00104  * Close network device
00105  *
00106  * @v netdev            Network device
00107  */
00108 static void skeleton_close ( struct net_device *netdev ) {
00109         struct skeleton_nic *skel = netdev->priv;
00110 
00111         DBGC ( skel, "SKELETON %p does not yet support close\n", skel );
00112 }
00113 
00114 /**
00115  * Transmit packet
00116  *
00117  * @v netdev            Network device
00118  * @v iobuf             I/O buffer
00119  * @ret rc              Return status code
00120  */
00121 static int skeleton_transmit ( struct net_device *netdev,
00122                                struct io_buffer *iobuf ) {
00123         struct skeleton_nic *skel = netdev->priv;
00124 
00125         DBGC ( skel, "SKELETON %p does not yet support transmit\n", skel );
00126         ( void ) iobuf;
00127         return -ENOTSUP;
00128 }
00129 
00130 /**
00131  * Poll for completed and received packets
00132  *
00133  * @v netdev            Network device
00134  */
00135 static void skeleton_poll ( struct net_device *netdev ) {
00136         struct skeleton_nic *skel = netdev->priv;
00137 
00138         /* Not yet implemented */
00139         ( void ) skel;
00140 }
00141 
00142 /**
00143  * Enable or disable interrupts
00144  *
00145  * @v netdev            Network device
00146  * @v enable            Interrupts should be enabled
00147  */
00148 static void skeleton_irq ( struct net_device *netdev, int enable ) {
00149         struct skeleton_nic *skel = netdev->priv;
00150 
00151         DBGC ( skel, "SKELETON %p does not yet support interrupts\n", skel );
00152         ( void ) enable;
00153 }
00154 
00155 /** Skeleton network device operations */
00156 static struct net_device_operations skeleton_operations = {
00157         .open           = skeleton_open,
00158         .close          = skeleton_close,
00159         .transmit       = skeleton_transmit,
00160         .poll           = skeleton_poll,
00161         .irq            = skeleton_irq,
00162 };
00163 
00164 /******************************************************************************
00165  *
00166  * PCI interface
00167  *
00168  ******************************************************************************
00169  */
00170 
00171 /**
00172  * Probe PCI device
00173  *
00174  * @v pci               PCI device
00175  * @ret rc              Return status code
00176  */
00177 static int skeleton_probe ( struct pci_device *pci ) {
00178         struct net_device *netdev;
00179         struct skeleton_nic *skel;
00180         int rc;
00181 
00182         /* Allocate and initialise net device */
00183         netdev = alloc_etherdev ( sizeof ( *skel ) );
00184         if ( ! netdev ) {
00185                 rc = -ENOMEM;
00186                 goto err_alloc;
00187         }
00188         netdev_init ( netdev, &skeleton_operations );
00189         skel = netdev->priv;
00190         pci_set_drvdata ( pci, netdev );
00191         netdev->dev = &pci->dev;
00192         memset ( skel, 0, sizeof ( *skel ) );
00193 
00194         /* Fix up PCI device */
00195         adjust_pci_device ( pci );
00196 
00197         /* Map registers */
00198         skel->regs = ioremap ( pci->membase, SKELETON_BAR_SIZE );
00199         if ( ! skel->regs ) {
00200                 rc = -ENODEV;
00201                 goto err_ioremap;
00202         }
00203 
00204         /* Reset the NIC */
00205         if ( ( rc = skeleton_reset ( skel ) ) != 0 )
00206                 goto err_reset;
00207 
00208         /* Register network device */
00209         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00210                 goto err_register_netdev;
00211 
00212         /* Set initial link state */
00213         skeleton_check_link ( netdev );
00214 
00215         return 0;
00216 
00217         unregister_netdev ( netdev );
00218  err_register_netdev:
00219         skeleton_reset ( skel );
00220  err_reset:
00221         iounmap ( skel->regs );
00222  err_ioremap:
00223         netdev_nullify ( netdev );
00224         netdev_put ( netdev );
00225  err_alloc:
00226         return rc;
00227 }
00228 
00229 /**
00230  * Remove PCI device
00231  *
00232  * @v pci               PCI device
00233  */
00234 static void skeleton_remove ( struct pci_device *pci ) {
00235         struct net_device *netdev = pci_get_drvdata ( pci );
00236         struct skeleton_nic *skel = netdev->priv;
00237 
00238         /* Unregister network device */
00239         unregister_netdev ( netdev );
00240 
00241         /* Reset card */
00242         skeleton_reset ( skel );
00243 
00244         /* Free network device */
00245         iounmap ( skel->regs );
00246         netdev_nullify ( netdev );
00247         netdev_put ( netdev );
00248 }
00249 
00250 /** Skeleton PCI device IDs */
00251 static struct pci_device_id skeleton_nics[] = {
00252         PCI_ROM ( 0x5ce1, 0x5ce1, "skel",       "Skeleton", 0 ),
00253 };
00254 
00255 /** Skeleton PCI driver */
00256 struct pci_driver skeleton_driver __pci_driver = {
00257         .ids = skeleton_nics,
00258         .id_count = ( sizeof ( skeleton_nics ) / sizeof ( skeleton_nics[0] ) ),
00259         .probe = skeleton_probe,
00260         .remove = skeleton_remove,
00261 };