doc: Update porting_drivers.txt
[dragonfly.git] / doc / porting_drivers.txt
CommitLineData
60e7fae5 1$DragonFly: doc/notes/porting_drivers.txt,v 1.4 2008/04/06 19:08:30 pavalos Exp $
4993a92b
MD
2
3 PORTING FREEBSD DRIVERS TO DRAGONFLY
4
5* Copy the driver code to the appropriate DragonFly directory. For example,
6 a disk driver /usr/src/sys/dev/blah in FreeBSD would likely be
7 /usr/src/sys/dev/disk/blah in DragonFly.
8
e732300c
AHJ
9* Keep all the CVS ids in the files for future reference point. If the files
10 don't have it, please add it to them. You can find them out from CVSWeb
11 repository or by checking out the specific source files with the FreeBSD
12 SVN client.
13 This could be automated in the case pkgsrc's SVN client had the set of
14 patches that provide this functionality.
15
e732300c 16* Remove FBSDID declaration and '#include <sys/cdefs.h>' as well.
4993a92b
MD
17
18* Driver local #include's probably use a <dev/blah/blah.h> path. These
19 need to be changed to "blah.h". '.' is not included in the #include
20 path in FreeBSD builds, but it is in DragonFly builds.
21
22* Other #include's may reference things in <dev/...> which in DragonFly
23 reside in <bus/...>. In particular, dev/pccard becomes bus/pccard.
24 Note that defines in FreeBSD's pccard_cis.h reside in DragonFly's
25 pccardreg.h .
26
07d0d38c
SW
27* The following kernel functions have been renamed in DragonFly:
28
29 malloc(), free() etc. -> kmalloc(), kfree() etc.
30 printf() etc. -> kprintf() etc.
31 psignal() -> ksignal()
d2da76f2 32 random() -> krandom()
07d0d38c 33
4993a92b 34* MUTEX conversion - mutexes are generally replaced by spinlocks. However,
72e64973 35 DragonFly spinlocks are more restrictive than FreeBSD mutexes so a
4993a92b
MD
36 direct replacement is not necessarily appropriate in all cases. A lockmgr
37 lock should be used when a direct replacement is not appropriate.
38 In particular, DragonFly does not allow recursive exclusive spinlocks
39 and does not allow multiple exclusive spinlocks to be held by any given
40 thread.
41
42 Instances of <sys/mutex.h> should be replaced with <sys/spinlock.h>.
43
44 When replacing mutexes with spinlocks it is a good idea to rename
45 the structural field (typically 'mtx') to something else (typically 'spin').
46
47 The &Giant mutex is typically converted to get_mplock() and rel_mplock().
48 However, there are places where FreeBSD unlocks giant around some code and
49 then relocks giant... those should simply be removed.
50
51 FreeBSD has weird callout + mutex functions. DragonFly does not integrate
52 the two. Instead, the driver in DragonFly must obtain the spinlocks
53 in question in the callback routine.
54
72e64973
SW
55 As a rule of thumb, MTX_DEF mutexes should be replaced with exclusive,
56 recursive lockmgr locks.
57
58 So, suppose the original code is using
59 struct mtx my_mtx;
60 you'd normally rename it to
61 struct lock my_lock;
62
63 and change the initialization from something like
64 mtx_init(&my_mtx, "mymtx", "whatever", MTX_DEF);
65 to
60e7fae5 66 lockinit(&my_lock, "mylock", 0, LK_CANRECURSE);
72e64973
SW
67
68 Destroying it is trivial,
69 mtx_destroy(&my_mtx);
70 becomes
71 lockuninit(&my_lock);
72
73 You use the same function for locking and unlocking a lockmgr lock,
74 so exchange
75 mtx_lock(&my_mtx);
76 with
77 lockmgr(&my_lock, LK_EXCLUSIVE);
78 and
79 mtx_unlock(&my_mtx);
80 with
81 lockmgr(&my_lock, LK_RELEASE);
82
83 For testing the lock status, one would use
84 lockstatus(&my_lock, curthread);
85 in place of
86 mtx_owned(&my_mtx);
87
88 An
89 mtx_trylock(&my_mtx);
90 call is replaced with
91 lockmgr(&my_lock, LK_EXCLUSIVE|LK_NOWAIT);
92
93 As for mtx_assert() calls, translate them like this:
94
95 mtx_assert(&my_mtx, MA_OWNED) -> KKASSERT(lockstatus(&my_lock, curthread) != 0)
96 mtx_assert(&my_mtx, MA_NOTOWNED) -> KKASSERT(lockstatus(&my_lock, curthread) == 0)
97
98 In DragonFly, lockstatus() does not return information about whether there have been
99 recursive lock acquisitions, so there is no generic way to emulate the
100
101 mtx_assert(&my_mtx, MA_OWNED|MA_RECURSED);
102 mtx_assert(&my_mtx, MA_OWNED|MA_NOTRECURSED);
103
104 calls.
4b3fb495
FT
105
106* rwlock conversion: Use lockmgr locks
72e64973 107
07d0d38c
SW
108* UMA conversion - generally speaking UMA should be converted to a standard
109 kmalloc.
4993a92b
MD
110
111 Note however that in FreeBSD M_NOWAIT is often used in cases where, in fact,
07d0d38c 112 the kmalloc cannot fail without blowing something up or causing a fatal
4993a92b
MD
113 (and very unexpected) I/O error. M_INTWAIT should be used for these cases.
114
115* CDEVSW conversion - see other devices. Generally speaking a major number
116 is needed and a function map needs to be specified more explicitly.
117
118 Most calls passing struct cdev pointers are dev_t's in DragonFly.
119
120 All device vectors in DragonFly pass a dev_<name>_args structure pointer
121 instead of explicit arguments.
122
123 Strategy calls - we pass BIO's and a lot of BUF fields are in the BIO
124 in FreeBSD, but left in the BUF in DragonFly. FreeBSD for some reason
125 names its struct bio pointers 'bp', its a good idea to rename them to 'bio'
126 to avoid confusion and have a struct buf *bp = bio->bio_buf; pointer to
127 access the buf.
128
d2da76f2
SW
129* MSLEEP/TSLEEP conversion. The DragonFly msleep/tsleep do not have 'PRI'
130 priorities. 0 should be used.
4993a92b 131
4993a92b
MD
132* BUS_* FUNCTIONS
133
134 bus_setup_intr() - replace INTR_TYPE_* flags with 0. There is an extra
135 argument for an interrupt interlock using the sys/serializer.h interface.
60e7fae5 136 This can either be left NULL or you can convert the spinlock(s) for
4993a92b
MD
137 the driver into serializer locks and integrate the interrupt service
138 routine with a serializer.
d2da76f2
SW
139
140* CAM CODE - cam_simq* code refcounts, so shared device queues (raid and
141 multi-channel devices) are not freed before all references have gone
142 away.
317f6748
FT
143
144* callout_drain() should be replaced by callout_stop_sync()
de612e47
FT
145
146* UNRHDR functions - DragonFly uses a more generic idr(9) subsystem
147 compatible with the Linux API of the same name
148
149 This LWN article describes it in details: http://lwn.net/Articles/103209/
150
151 A typical conversion looks like this:
152
153 #include <sys/idr.h>
154
155 free_unr() has to be replaced by idr_remove()
156
157 alloc_unr() has to be replaced by a code sequence using idr_pre_get and
158 idr_get_new such as this one:
159
160 retry:
161 if (idr_pre_get(xxx) ==0) {
162 kprintf("Memory allocation error\n");
163 return error;
164 }
165 spin_lock(xxx);
166 ret = idr_get_new(xxx);
167 spin_unlock(xxx);
168 if (ret == EAGAIN)
169 goto retry;
170
4dd401bd 171* MPASS macro - Replace it with KKASSERT
2764c241 172
cf396422
FT
173
174* PROC_LOCK / PROC_UNLOCK: to be determined on a case-by-case basis
175
176 Some of the time these macros can be removed entirely
177
178 In some cases, some locking must be done; lwkt_gettoken(&proc_token)
179 and the corresponding lwkt_reltoken() call should be good replacements
180
181 It is not a good idea to blindly implement these macros globally, some
182 particular proc subsystem locking semantics differ enough between FreeBSD
183 and DragonFly that this would cause problems
184
185
2764c241
AHJ
186* In DragonFly 3.3 format specifier %D was removed from kprintf. As a
187 replacement functions kether_ntoa() and hexncpy() were added.
188
189 - Ethernet address (MAC) to its hexadecimal form:
190
191 char ethstr[ETHER_ADDRSTRLEN + 1];
192 u_char hwaddr[6];
193
194 kprintf("MAC address %s\n", kether_ntoa(hwaddr, ethstr)
195
196 - Generic conversion (block of bytes to hexadecimal form):
197
198 char hexstr[18];
199 u_char mydata[6] = {1, 2, 3, 4, 5 ,6};
200
201 /*
202 * Below statement would print:
203 *
204 * 01-02-03-04-05-06
205 */
206 kprintf("%s\n", hexncpy(mydata, 6, hexstr, HEX_NCPYLEN(6), "-"));
4b3fb495
FT
207
208* TAILQ_XXX_SAFE
209
210 Use TAILQ_XXX_MUTABLE; the macros have the same effect, only the name is
211 different
212
213* kern_yield()
214
215 Replace by lwkt_yield()
216
217* vm_page_lock() and vm_page_unlock()
218
219 Not needed on DragonFly, remove these calls
220
221* vm_pager_get_pages()
222
223 Removed, use vm_pager_get_page() instead
224
225* VPO_BUSY
226
227 Replace by PG_BUSY
228
229* kern_psignal()
230
231 Replace by ksignal()