~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/Documentation/sparc/sbus_drivers.txt

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  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.

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.