iPXE
device.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_SECBOOT ( PERMITTED );
26 
27 #include <string.h>
28 #include <ipxe/list.h>
29 #include <ipxe/tables.h>
30 #include <ipxe/init.h>
31 #include <ipxe/interface.h>
32 #include <ipxe/device.h>
33 
34 /**
35  * @file
36  *
37  * Device model
38  *
39  */
40 
41 /** Registered root devices */
42 static LIST_HEAD ( devices );
43 
44 /** Device removal inhibition counter */
46 
47 /**
48  * Probe a root device
49  *
50  * @v rootdev Root device
51  * @ret rc Return status code
52  */
53 static int rootdev_probe ( struct root_device *rootdev ) {
54  int rc;
55 
56  DBG ( "Adding %s root bus\n", rootdev->dev.name );
57  if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) {
58  DBG ( "Failed to add %s root bus: %s\n",
59  rootdev->dev.name, strerror ( rc ) );
60  return rc;
61  }
62 
63  return 0;
64 }
65 
66 /**
67  * Remove a root device
68  *
69  * @v rootdev Root device
70  */
71 static void rootdev_remove ( struct root_device *rootdev ) {
72  rootdev->driver->remove ( rootdev );
73  DBG ( "Removed %s root bus\n", rootdev->dev.name );
74 }
75 
76 /**
77  * Probe all devices
78  *
79  * This initiates probing for all devices in the system. After this
80  * call, the device hierarchy will be populated, and all hardware
81  * should be ready to use.
82  */
83 static void probe_devices ( void ) {
84  struct root_device *rootdev;
85  int rc;
86 
87  for_each_table_entry ( rootdev, ROOT_DEVICES ) {
88  list_add ( &rootdev->dev.siblings, &devices );
89  INIT_LIST_HEAD ( &rootdev->dev.children );
90  if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
91  list_del ( &rootdev->dev.siblings );
92  }
93 }
94 
95 /**
96  * Remove all devices
97  *
98  */
99 static void remove_devices ( int booting __unused ) {
100  struct root_device *rootdev;
101  struct root_device *tmp;
102 
103  if ( device_keep_count != 0 ) {
104  DBG ( "Refusing to remove devices on shutdown\n" );
105  return;
106  }
107 
108  list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
109  rootdev_remove ( rootdev );
110  list_del ( &rootdev->dev.siblings );
111  }
112 }
113 
114 struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
115  .name = "devices",
116  .startup = probe_devices,
117  .shutdown = remove_devices,
118 };
119 
120 /**
121  * Identify a device behind an interface
122  *
123  * @v intf Interface
124  * @ret device Device, or NULL
125  */
126 struct device * identify_device ( struct interface *intf ) {
127  struct interface *dest;
128  identify_device_TYPE ( void * ) *op =
130  void *object = intf_object ( dest );
131  void *device;
132 
133  if ( op ) {
134  device = op ( object );
135  } else {
136  /* Default is to return NULL */
137  device = NULL;
138  }
139 
140  intf_put ( dest );
141  return device;
142 }
#define STARTUP_NORMAL
Normal startup.
Definition: init.h:65
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:70
int device_keep_count
Device removal inhibition counter.
Definition: device.c:45
void(* remove)(struct root_device *rootdev)
Remove root device.
Definition: device.h:129
char name[40]
Name.
Definition: device.h:79
A root device.
Definition: device.h:98
#define ROOT_DEVICES
Root device table.
Definition: device.h:133
uint16_t device
Device ID.
Definition: ena.h:24
struct device dev
Device chain.
Definition: device.h:103
const char * name
Definition: init.h:44
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:160
struct interface * intf
Original interface.
Definition: interface.h:159
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned long tmp
Definition: linux_pci.h:65
A startup/shutdown function.
Definition: init.h:43
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
static LIST_HEAD(devices)
Registered root devices.
A hardware device.
Definition: device.h:77
An object interface.
Definition: interface.h:125
struct root_driver * driver
Root device driver.
Definition: device.h:105
FILE_SECBOOT(PERMITTED)
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
Object interfaces.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:459
Linked lists.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void remove_devices(int booting __unused)
Remove all devices.
Definition: device.c:99
struct list_head siblings
Devices on the same bus.
Definition: device.h:85
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
static int rootdev_probe(struct root_device *rootdev)
Probe a root device.
Definition: device.c:53
static void rootdev_remove(struct root_device *rootdev)
Remove a root device.
Definition: device.c:71
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:120
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:46
static void probe_devices(void)
Probe all devices.
Definition: device.c:83
struct list_head children
Devices attached to this device.
Definition: device.h:87
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:150
#define identify_device_TYPE(object_type)
Definition: device.h:178
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
Linker tables.
Device model.
struct startup_fn startup_devices __startup_fn(STARTUP_NORMAL)
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition: device.c:126
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:270