device.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <string.h>
00022 #include <gpxe/list.h>
00023 #include <gpxe/tables.h>
00024 #include <gpxe/device.h>
00025 #include <gpxe/init.h>
00026 
00027 /**
00028  * @file
00029  *
00030  * Device model
00031  *
00032  */
00033 
00034 /** Registered root devices */
00035 static LIST_HEAD ( devices );
00036 
00037 /**
00038  * Probe a root device
00039  *
00040  * @v rootdev           Root device
00041  * @ret rc              Return status code
00042  */
00043 static int rootdev_probe ( struct root_device *rootdev ) {
00044         int rc;
00045 
00046         DBG ( "Adding %s root bus\n", rootdev->dev.name );
00047         if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) {
00048                 DBG ( "Failed to add %s root bus: %s\n",
00049                       rootdev->dev.name, strerror ( rc ) );
00050                 return rc;
00051         }
00052 
00053         return 0;
00054 }
00055 
00056 /**
00057  * Remove a root device
00058  *
00059  * @v rootdev           Root device
00060  */
00061 static void rootdev_remove ( struct root_device *rootdev ) {
00062         rootdev->driver->remove ( rootdev );
00063         DBG ( "Removed %s root bus\n", rootdev->dev.name );
00064 }
00065 
00066 /**
00067  * Probe all devices
00068  *
00069  * This initiates probing for all devices in the system.  After this
00070  * call, the device hierarchy will be populated, and all hardware
00071  * should be ready to use.
00072  */
00073 static void probe_devices ( void ) {
00074         struct root_device *rootdev;
00075         int rc;
00076 
00077         for_each_table_entry ( rootdev, ROOT_DEVICES ) {
00078                 list_add ( &rootdev->dev.siblings, &devices );
00079                 INIT_LIST_HEAD ( &rootdev->dev.children );
00080                 if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
00081                         list_del ( &rootdev->dev.siblings );
00082         }
00083 }
00084 
00085 /**
00086  * Remove all devices
00087  *
00088  */
00089 static void remove_devices ( int flags ) {
00090         struct root_device *rootdev;
00091         struct root_device *tmp;
00092 
00093         if ( flags & SHUTDOWN_KEEP_DEVICES ) {
00094                 DBG ( "Refusing to remove devices on shutdown\n" );
00095                 return;
00096         }
00097 
00098         list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
00099                 rootdev_remove ( rootdev );
00100                 list_del ( &rootdev->dev.siblings );
00101         }
00102 }
00103 
00104 struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
00105         .startup = probe_devices,
00106         .shutdown = remove_devices,
00107 };

Generated on Tue Apr 6 20:00:51 2010 for gPXE by  doxygen 1.5.7.1