Browse Source

Trying to create a bus API.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
a95b458660
1 changed files with 161 additions and 0 deletions
  1. 161
    0
      src/include/bus.h

+ 161
- 0
src/include/bus.h View File

@@ -0,0 +1,161 @@
1
+#ifndef BUS_H
2
+#define BUS_H
3
+
4
+#include "stdint.h"
5
+
6
+/*
7
+ * When looking at the following data structures, mentally substitute
8
+ * "<bus>_" in place of "bus_" and everything will become clear.
9
+ * "struct bus_location" becomes "struct <bus>_location", which means
10
+ * "the location of a device on a <bus> bus", where <bus> is a
11
+ * particular type of bus such as "pci" or "isapnp".
12
+ *
13
+ */
14
+
15
+/*
16
+ * A physical device location.
17
+ *
18
+ */
19
+#define BUS_LOCATION_SIZE 4
20
+struct bus_location {
21
+	char bytes[BUS_LOCATION_SIZE];
22
+};
23
+
24
+/* 
25
+ * A structure fully describing a physical device.
26
+ *
27
+ */
28
+#define BUS_DEVICE_SIZE 32
29
+struct bus_device {
30
+	char bytes[BUS_DEVICE_SIZE];
31
+};
32
+
33
+/*
34
+ * Individual buses will have different sizes for their <bus>_location
35
+ * and <bus>_device structures.  We need to be able to allocate static
36
+ * storage that's large enough to contain these structures for any
37
+ * bus type that's being used in the current binary.
38
+ *
39
+ * We can't just create a union of all the various types, because some
40
+ * may be architecture-dependent (and some are even embedded in
41
+ * specific drivers, e.g. 3c509), so this would quickly get messy.
42
+ *
43
+ * We could use the magic of common symbols.  Each bus could declare a
44
+ * common symbol with the name "_bus_device" of the correct size; this
45
+ * is easily done using code like
46
+ *	struct pci_device _bus_device;
47
+ * The linker would then use the largest size of the "_bus_device"
48
+ * symbol in any included object, thus giving us a single _bus_device
49
+ * symbol of *exactly* the required size.  However, there's no way to
50
+ * extract the size of this symbol, either directly as a linker symbol
51
+ * ("_bus_device_size = SIZEOF(_bus_device)"; the linker language just
52
+ * doesn't provide this construct) or via any linker trickery I can
53
+ * think of (such as creating a special common symbol section just for
54
+ * this symbol then using SIZE(section) to read the size of the
55
+ * section; ld recognises only a single common symbol section called
56
+ * "COMMON").
57
+ *
58
+ * Since there's no way to get the size of the symbol, this
59
+ * effectively limits us to just one instance of the symbol.  This is
60
+ * all very well for the simple case of "just boot from any single
61
+ * device you can", but becomes limiting when you want to do things
62
+ * like introducing PCMCIA buses (which must instantiate other devices
63
+ * such as PCMCIA controllers).
64
+ *
65
+ * So, we declare the maximum sizes of these constructions to be
66
+ * compile-time constants.  Each individual bus driver should define
67
+ * its own struct <bus>_location and struct <bus>_device however it
68
+ * likes, and can freely cast pointers from struct bus_location to
69
+ * struct <bus>_location (and similarly for bus_device).  To guard
70
+ * against bounding errors, each bus driver *MUST* use the macros
71
+ * BUS_LOCATION_CHECK() and BUS_DEVICE_CHECK(), as in:
72
+ *
73
+ *   BUS_LOCATION_CHECK ( struct pci_location );
74
+ *   BUS_DEVICE_CHECK ( struct pci_device );
75
+ *
76
+ * These macros will generate a link-time error if the size of the
77
+ * <bus> structure exceeds the declared maximum size.
78
+ *
79
+ * The macros will generate no binary object code, but must be placed
80
+ * inside a function (in order to generate syntactically valid C).
81
+ * The easiest wy to do this is to place them in the
82
+ * <bus>_next_location() function.
83
+ *
84
+ * If anyone can think of a better way of doing this that avoids *ALL*
85
+ * of the problems described above, please implement it!
86
+ *
87
+ */
88
+
89
+#define LINKER_ASSERT(test,error_symbol)		\
90
+	if ( ! (test) ) {				\
91
+		extern void error_symbol ( void );	\
92
+		error_symbol();				\
93
+	}
94
+
95
+#define BUS_LOCATION_CHECK(datatype) \
96
+	LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_location) ),
97
+		       __BUS_LOCATION_SIZE_is_too_small__see_dev_h )
98
+#define BUS_DEVICE_CHECK(datatype) \
99
+	LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_device) ),
100
+		       __BUS_DEVICE_SIZE_is_too_small__see_dev_h )
101
+
102
+/*
103
+ * A description of a device.  This is used to send information about
104
+ * the device to a DHCP server, and to provide a text string to
105
+ * describe the device to the user.
106
+ *
107
+ * Note that "text" is allowed to be NULL, in which case the
108
+ * describe_device() method will print the information directly to the
109
+ * console rather than writing it into a buffer.  (This happens
110
+ * transparently because sprintf(NULL,...) is exactly equivalent to
111
+ * printf(...) in our vsprintf.c).
112
+ *
113
+ */
114
+struct bus_description {
115
+	char *text;
116
+	uint16_t	vendor_id;
117
+	uint16_t	device_id;
118
+	uint8_t		bus_type;
119
+};
120
+
121
+/*
122
+ * A driver definition
123
+ *
124
+ */
125
+struct bus_driver;
126
+
127
+/*
128
+ * Bus-level operations.
129
+ *
130
+ * int next_location ( struct bus_location * bus_location )
131
+ *
132
+ *	Increment bus_location to point to the next possible device on
133
+ *	the bus (e.g. the next PCI busdevfn, or the next ISAPnP CSN).
134
+ *	If there are no more valid locations, return 0 and leave
135
+ *	struct bus_location zeroed, otherwise return true.
136
+ *
137
+ * int fill_device ( struct bus_location *bus_location,
138
+ *		     struct bus_device *bus_device )
139
+ *
140
+ *	Fill out a bus_device structure with the parameters for the
141
+ *	device at bus_location.  (For example, fill in the PCI vendor
142
+ *	and device IDs).  Return true if there is a device physically
143
+ *	present at this location, otherwise 0.
144
+ *
145
+ * int check_driver ( )
146
+ *
147
+ */
148
+struct bus_operations {
149
+	int ( *next_location ) ( struct bus_location * bus_location );
150
+	int ( *fill_device ) ( struct bus_location * bus_location,
151
+			       struct bus_device * bus_device );
152
+	int ( *check_driver ) ( struct bus_device * bus_device,
153
+				struct bus_driver * bus_driver );
154
+	void ( *describe_device ) ( struct bus_device * bus_device,
155
+				    struct bus_driver * bus_driver,
156
+				    struct bus_description * bus_description );
157
+};
158
+
159
+
160
+
161
+#endif /* BUS_H */

Loading…
Cancel
Save