]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | Writing SBUS Drivers | |
3 | ||
4 | David S. Miller (davem@redhat.com) | |
5 | ||
6 | The SBUS driver interfaces of the Linux kernel have been | |
7 | revamped completely for 2.4.x for several reasons. Foremost were | |
8 | performance and complexity concerns. This document details these | |
9 | new interfaces and how they are used to write an SBUS device driver. | |
10 | ||
11 | SBUS drivers need to include <asm/sbus.h> to get access | |
12 | to functions and structures described here. | |
13 | ||
14 | Probing and Detection | |
15 | ||
16 | Each SBUS device inside the machine is described by a | |
17 | structure called "struct sbus_dev". Likewise, each SBUS bus | |
18 | found in the system is described by a "struct sbus_bus". For | |
19 | each SBUS bus, the devices underneath are hung in a tree-like | |
20 | fashion off of the bus structure. | |
21 | ||
22 | The SBUS device structure contains enough information | |
23 | for you to implement your device probing algorithm and obtain | |
24 | the bits necessary to run your device. The most commonly | |
25 | used members of this structure, and their typical usage, | |
26 | will be detailed below. | |
27 | ||
28 | Here is how probing is performed by an SBUS driver | |
29 | under Linux: | |
30 | ||
31 | static void init_one_mydevice(struct sbus_dev *sdev) | |
32 | { | |
33 | ... | |
34 | } | |
35 | ||
36 | static int mydevice_match(struct sbus_dev *sdev) | |
37 | { | |
38 | if (some_criteria(sdev)) | |
39 | return 1; | |
40 | return 0; | |
41 | } | |
42 | ||
43 | static void mydevice_probe(void) | |
44 | { | |
45 | struct sbus_bus *sbus; | |
46 | struct sbus_dev *sdev; | |
47 | ||
48 | for_each_sbus(sbus) { | |
49 | for_each_sbusdev(sdev, sbus) { | |
50 | if (mydevice_match(sdev)) | |
51 | init_one_mydevice(sdev); | |
52 | } | |
53 | } | |
54 | } | |
55 | ||
56 | All this does is walk through all SBUS devices in the | |
57 | system, checks each to see if it is of the type which | |
58 | your driver is written for, and if so it calls the init | |
59 | routine to attach the device and prepare to drive it. | |
60 | ||
61 | "init_one_mydevice" might do things like allocate software | |
62 | state structures, map in I/O registers, place the hardware | |
63 | into an initialized state, etc. | |
64 | ||
65 | Mapping and Accessing I/O Registers | |
66 | ||
67 | Each SBUS device structure contains an array of descriptors | |
68 | which describe each register set. We abuse struct resource for that. | |
69 | They each correspond to the "reg" properties provided by the OBP firmware. | |
70 | ||
71 | Before you can access your device's registers you must map | |
72 | them. And later if you wish to shutdown your driver (for module | |
73 | unload or similar) you must unmap them. You must treat them as | |
74 | a resource, which you allocate (map) before using and free up | |
75 | (unmap) when you are done with it. | |
76 | ||
77 | The mapping information is stored in an opaque value | |
78 | typed as an "unsigned long". This is the type of the return value | |
79 | of the mapping interface, and the arguments to the unmapping | |
80 | interface. Let's say you want to map the first set of registers. | |
81 | Perhaps part of your driver software state structure looks like: | |
82 | ||
83 | struct mydevice { | |
84 | unsigned long control_regs; | |
85 | ... | |
86 | struct sbus_dev *sdev; | |
87 | ... | |
88 | }; | |
89 | ||
90 | At initialization time you then use the sbus_ioremap | |
91 | interface to map in your registers, like so: | |
92 | ||
93 | static void init_one_mydevice(struct sbus_dev *sdev) | |
94 | { | |
95 | struct mydevice *mp; | |
96 | ... | |
97 | ||
98 | mp->control_regs = sbus_ioremap(&sdev->resource[0], 0, | |
99 | CONTROL_REGS_SIZE, "mydevice regs"); | |
100 | if (!mp->control_regs) { | |
101 | /* Failure, cleanup and return. */ | |
102 | } | |
103 | } | |
104 | ||
105 | Second argument to sbus_ioremap is an offset for | |
106 | cranky devices with broken OBP PROM. The sbus_ioremap uses only | |
107 | a start address and flags from the resource structure. | |
108 | Therefore it is possible to use the same resource to map | |
109 | several sets of registers or even to fabricate a resource | |
110 | structure if driver gets physical address from some private place. | |
111 | This practice is discouraged though. Use whatever OBP PROM | |
112 | provided to you. | |
113 | ||
114 | And here is how you might unmap these registers later at | |
115 | driver shutdown or module unload time, using the sbus_iounmap | |
116 | interface: | |
117 | ||
118 | static void mydevice_unmap_regs(struct mydevice *mp) | |
119 | { | |
120 | sbus_iounmap(mp->control_regs, CONTROL_REGS_SIZE); | |
121 | } | |
122 | ||
123 | Finally, to actually access your registers there are 6 | |
124 | interface routines at your disposal. Accesses are byte (8 bit), | |
125 | word (16 bit), or longword (32 bit) sized. Here they are: | |
126 | ||
127 | u8 sbus_readb(unsigned long reg) /* read byte */ | |
128 | u16 sbus_readw(unsigned long reg) /* read word */ | |
129 | u32 sbus_readl(unsigned long reg) /* read longword */ | |
130 | void sbus_writeb(u8 value, unsigned long reg) /* write byte */ | |
131 | void sbus_writew(u16 value, unsigned long reg) /* write word */ | |
132 | void sbus_writel(u32 value, unsigned long reg) /* write longword */ | |
133 | ||
134 | So, let's say your device has a control register of some sort | |
135 | at offset zero. The following might implement resetting your device: | |
136 | ||
137 | #define CONTROL 0x00UL | |
138 | ||
139 | #define CONTROL_RESET 0x00000001 /* Reset hardware */ | |
140 | ||
141 | static void mydevice_reset(struct mydevice *mp) | |
142 | { | |
143 | sbus_writel(CONTROL_RESET, mp->regs + CONTROL); | |
144 | } | |
145 | ||
146 | Or perhaps there is a data port register at an offset of | |
147 | 16 bytes which allows you to read bytes from a fifo in the device: | |
148 | ||
149 | #define DATA 0x10UL | |
150 | ||
151 | static u8 mydevice_get_byte(struct mydevice *mp) | |
152 | { | |
153 | return sbus_readb(mp->regs + DATA); | |
154 | } | |
155 | ||
156 | It's pretty straightforward, and clueful readers may have | |
157 | noticed that these interfaces mimick the PCI interfaces of the | |
158 | Linux kernel. This was not by accident. | |
159 | ||
160 | WARNING: | |
161 | ||
162 | DO NOT try to treat these opaque register mapping | |
163 | values as a memory mapped pointer to some structure | |
164 | which you can dereference. | |
165 | ||
166 | It may be memory mapped, it may not be. In fact it | |
167 | could be a physical address, or it could be the time | |
168 | of day xor'd with 0xdeadbeef. :-) | |
169 | ||
170 | Whatever it is, it's an implementation detail. The | |
171 | interface was done this way to shield the driver | |
172 | author from such complexities. | |
173 | ||
174 | Doing DVMA | |
175 | ||
176 | SBUS devices can perform DMA transactions in a way similar | |
177 | to PCI but dissimilar to ISA, e.g. DMA masters supply address. | |
178 | In contrast to PCI, however, that address (a bus address) is | |
179 | translated by IOMMU before a memory access is performed and therefore | |
180 | it is virtual. Sun calls this procedure DVMA. | |
181 | ||
182 | Linux supports two styles of using SBUS DVMA: "consistent memory" | |
183 | and "streaming DVMA". CPU view of consistent memory chunk is, well, | |
184 | consistent with a view of a device. Think of it as an uncached memory. | |
185 | Typically this way of doing DVMA is not very fast and drivers use it | |
186 | mostly for control blocks or queues. On some CPUs we cannot flush or | |
187 | invalidate individual pages or cache lines and doing explicit flushing | |
188 | over ever little byte in every control block would be wasteful. | |
189 | ||
190 | Streaming DVMA is a preferred way to transfer large amounts of data. | |
191 | This process works in the following way: | |
192 | 1. a CPU stops accessing a certain part of memory, | |
193 | flushes its caches covering that memory; | |
194 | 2. a device does DVMA accesses, then posts an interrupt; | |
195 | 3. CPU invalidates its caches and starts to access the memory. | |
196 | ||
197 | A single streaming DVMA operation can touch several discontiguous | |
198 | regions of a virtual bus address space. This is called a scatter-gather | |
199 | DVMA. | |
200 | ||
201 | [TBD: Why do not we neither Solaris attempt to map disjoint pages | |
202 | into a single virtual chunk with the help of IOMMU, so that non SG | |
203 | DVMA masters would do SG? It'd be very helpful for RAID.] | |
204 | ||
205 | In order to perform a consistent DVMA a driver does something | |
206 | like the following: | |
207 | ||
208 | char *mem; /* Address in the CPU space */ | |
209 | u32 busa; /* Address in the SBus space */ | |
210 | ||
211 | mem = (char *) sbus_alloc_consistent(sdev, MYMEMSIZE, &busa); | |
212 | ||
213 | Then mem is used when CPU accesses this memory and u32 | |
214 | is fed to the device so that it can do DVMA. This is typically | |
215 | done with an sbus_writel() into some device register. | |
216 | ||
217 | Do not forget to free the DVMA resources once you are done: | |
218 | ||
219 | sbus_free_consistent(sdev, MYMEMSIZE, mem, busa); | |
220 | ||
221 | Streaming DVMA is more interesting. First you allocate some | |
222 | memory suitable for it or pin down some user pages. Then it all works | |
223 | like this: | |
224 | ||
225 | char *mem = argumen1; | |
226 | unsigned int size = argument2; | |
227 | u32 busa; /* Address in the SBus space */ | |
228 | ||
229 | *mem = 1; /* CPU can access */ | |
230 | busa = sbus_map_single(sdev, mem, size); | |
231 | if (busa == 0) ....... | |
232 | ||
233 | /* Tell the device to use busa here */ | |
234 | /* CPU cannot access the memory without sbus_dma_sync_single() */ | |
235 | ||
236 | sbus_unmap_single(sdev, busa, size); | |
237 | if (*mem == 0) .... /* CPU can access again */ | |
238 | ||
239 | It is possible to retain mappings and ask the device to | |
240 | access data again and again without calling sbus_unmap_single. | |
241 | However, CPU caches must be invalidated with sbus_dma_sync_single | |
242 | before such access. | |
243 | ||
244 | [TBD but what about writeback caches here... do we have any?] | |
245 | ||
246 | There is an equivalent set of functions doing the same thing | |
247 | only with several memory segments at once for devices capable of | |
248 | scatter-gather transfers. Use the Source, Luke. | |
249 | ||
250 | Examples | |
251 | ||
252 | drivers/net/sunhme.c | |
253 | This is a complicated driver which illustrates many concepts | |
254 | discussed above and plus it handles both PCI and SBUS boards. | |
255 | ||
256 | drivers/scsi/esp.c | |
257 | Check it out for scatter-gather DVMA. | |
258 | ||
259 | drivers/sbus/char/bpp.c | |
260 | A non-DVMA device. | |
261 | ||
262 | drivers/net/sunlance.c | |
263 | Lance driver abuses consistent mappings for data transfer. | |
264 | It is a nifty trick which we do not particularly recommend... | |
265 | Just check it out and know that it's legal. | |
266 | ||
267 | Bad examples, do NOT use | |
268 | ||
269 | drivers/video/cgsix.c | |
270 | This one uses result of sbus_ioremap as if it is an address. | |
271 | This does NOT work on sparc64 and therefore is broken. We will | |
272 | convert it at a later date. |