xref: /dragonfly/doc/porting_drivers.txt (revision ac392440)
16eef04ebSFrançois Tigeot		    PORTING FREEBSD DRIVERS TO DRAGONFLY
26eef04ebSFrançois Tigeot
36eef04ebSFrançois Tigeot* Copy the driver code to the appropriate DragonFly directory.  For example,
46eef04ebSFrançois Tigeot  a disk driver /usr/src/sys/dev/blah in FreeBSD would likely be
56eef04ebSFrançois Tigeot  /usr/src/sys/dev/disk/blah in DragonFly.
66eef04ebSFrançois Tigeot
7efb850f9SSascha Wildner* Keep all the SVN IDs in the files as a future reference point. dports' SVN
845fa0bf8SSascha Wildner  will do that by default. When using the FreeBSD git repo, please note the
9efb850f9SSascha Wildner  files' IDs manually, either in the files themselves or in the commit message.
10efb850f9SSascha Wildner  The general idea is that it must not get lost.
116eef04ebSFrançois Tigeot
126eef04ebSFrançois Tigeot* Driver local #include's probably use a <dev/blah/blah.h> path.  These
136eef04ebSFrançois Tigeot  need to be changed to "blah.h".   '.' is not included in the #include
146eef04ebSFrançois Tigeot  path in FreeBSD builds, but it is in DragonFly builds.
156eef04ebSFrançois Tigeot
166eef04ebSFrançois Tigeot* Other #include's may reference things in <dev/...> which in DragonFly
176eef04ebSFrançois Tigeot  reside in <bus/...>.  In particular, dev/pccard becomes bus/pccard.
186eef04ebSFrançois Tigeot  Note that defines in FreeBSD's pccard_cis.h reside in DragonFly's
196eef04ebSFrançois Tigeot  pccardreg.h .
206eef04ebSFrançois Tigeot
216eef04ebSFrançois Tigeot* The following kernel functions have been renamed in DragonFly:
226eef04ebSFrançois Tigeot
236eef04ebSFrançois Tigeot  malloc(), free() etc.	->	kmalloc(), kfree() etc.
246eef04ebSFrançois Tigeot  printf() etc.		->	kprintf() etc.
256eef04ebSFrançois Tigeot  psignal()		->	ksignal()
266eef04ebSFrançois Tigeot  random()		->	krandom()
276eef04ebSFrançois Tigeot
286eef04ebSFrançois Tigeot* MUTEX conversion - mutexes are generally replaced by spinlocks.  However,
296eef04ebSFrançois Tigeot  DragonFly spinlocks are more restrictive than FreeBSD mutexes so a
306eef04ebSFrançois Tigeot  direct replacement is not necessarily appropriate in all cases.  A lockmgr
316eef04ebSFrançois Tigeot  lock should be used when a direct replacement is not appropriate.
326eef04ebSFrançois Tigeot  In particular, DragonFly does not allow recursive exclusive spinlocks
336eef04ebSFrançois Tigeot  and does not allow multiple exclusive spinlocks to be held by any given
346eef04ebSFrançois Tigeot  thread.
356eef04ebSFrançois Tigeot
366eef04ebSFrançois Tigeot  Instances of <sys/mutex.h> should be replaced with <sys/spinlock.h>.
376eef04ebSFrançois Tigeot
386eef04ebSFrançois Tigeot  When replacing mutexes with spinlocks it is a good idea to rename
396eef04ebSFrançois Tigeot  the structural field (typically 'mtx') to something else (typically 'spin').
406eef04ebSFrançois Tigeot
416eef04ebSFrançois Tigeot  The &Giant mutex is typically converted to get_mplock() and rel_mplock().
426eef04ebSFrançois Tigeot  However, there are places where FreeBSD unlocks giant around some code and
436eef04ebSFrançois Tigeot  then relocks giant... those should simply be removed.
446eef04ebSFrançois Tigeot
456eef04ebSFrançois Tigeot  FreeBSD has weird callout + mutex functions.  DragonFly does not integrate
466eef04ebSFrançois Tigeot  the two.  Instead, the driver in DragonFly must obtain the spinlocks
476eef04ebSFrançois Tigeot  in question in the callback routine.
486eef04ebSFrançois Tigeot
496eef04ebSFrançois Tigeot  As a rule of thumb, MTX_DEF mutexes should be replaced with exclusive,
506eef04ebSFrançois Tigeot  recursive lockmgr locks.
516eef04ebSFrançois Tigeot
526eef04ebSFrançois Tigeot  So, suppose the original code is using
536eef04ebSFrançois Tigeot	struct mtx my_mtx;
546eef04ebSFrançois Tigeot  you'd normally rename it to
556eef04ebSFrançois Tigeot	struct lock my_lock;
566eef04ebSFrançois Tigeot
576eef04ebSFrançois Tigeot  and change the initialization from something like
586eef04ebSFrançois Tigeot	mtx_init(&my_mtx, "mymtx", "whatever", MTX_DEF);
596eef04ebSFrançois Tigeot  to
606eef04ebSFrançois Tigeot	lockinit(&my_lock, "mylock", 0, LK_CANRECURSE);
616eef04ebSFrançois Tigeot
626eef04ebSFrançois Tigeot  Destroying it is trivial,
636eef04ebSFrançois Tigeot	mtx_destroy(&my_mtx);
646eef04ebSFrançois Tigeot  becomes
656eef04ebSFrançois Tigeot	lockuninit(&my_lock);
666eef04ebSFrançois Tigeot
676eef04ebSFrançois Tigeot  You use the same function for locking and unlocking a lockmgr lock,
686eef04ebSFrançois Tigeot  so exchange
696eef04ebSFrançois Tigeot	mtx_lock(&my_mtx);
706eef04ebSFrançois Tigeot  with
716eef04ebSFrançois Tigeot	lockmgr(&my_lock, LK_EXCLUSIVE);
726eef04ebSFrançois Tigeot  and
736eef04ebSFrançois Tigeot	mtx_unlock(&my_mtx);
746eef04ebSFrançois Tigeot  with
756eef04ebSFrançois Tigeot	lockmgr(&my_lock, LK_RELEASE);
766eef04ebSFrançois Tigeot
776eef04ebSFrançois Tigeot  For testing the lock status, one would use
786eef04ebSFrançois Tigeot	lockstatus(&my_lock, curthread);
796eef04ebSFrançois Tigeot  in place of
806eef04ebSFrançois Tigeot	mtx_owned(&my_mtx);
816eef04ebSFrançois Tigeot
826eef04ebSFrançois Tigeot  An
836eef04ebSFrançois Tigeot	mtx_trylock(&my_mtx);
846eef04ebSFrançois Tigeot  call is replaced with
85*a9ea4065SSascha Wildner	lockmgr_try(&my_lock, LK_EXCLUSIVE);
866eef04ebSFrançois Tigeot
876eef04ebSFrançois Tigeot  As for mtx_assert() calls, translate them like this:
886eef04ebSFrançois Tigeot
896eef04ebSFrançois Tigeot	mtx_assert(&my_mtx, MA_OWNED) -> KKASSERT(lockstatus(&my_lock, curthread) != 0)
906eef04ebSFrançois Tigeot	mtx_assert(&my_mtx, MA_NOTOWNED) -> KKASSERT(lockstatus(&my_lock, curthread) == 0)
916eef04ebSFrançois Tigeot
926eef04ebSFrançois Tigeot  In DragonFly, lockstatus() does not return information about whether there have been
936eef04ebSFrançois Tigeot  recursive lock acquisitions, so there is no generic way to emulate the
946eef04ebSFrançois Tigeot
956eef04ebSFrançois Tigeot	mtx_assert(&my_mtx, MA_OWNED|MA_RECURSED);
966eef04ebSFrançois Tigeot	mtx_assert(&my_mtx, MA_OWNED|MA_NOTRECURSED);
976eef04ebSFrançois Tigeot
986eef04ebSFrançois Tigeot  calls.
996eef04ebSFrançois Tigeot
1004b3fb495SFrançois Tigeot* rwlock conversion: Use lockmgr locks
1014b3fb495SFrançois Tigeot
1026eef04ebSFrançois Tigeot* UMA conversion - generally speaking UMA should be converted to a standard
1036eef04ebSFrançois Tigeot  kmalloc.
1046eef04ebSFrançois Tigeot
1056eef04ebSFrançois Tigeot  Note however that in FreeBSD M_NOWAIT is often used in cases where, in fact,
1066eef04ebSFrançois Tigeot  the kmalloc cannot fail without blowing something up or causing a fatal
1076eef04ebSFrançois Tigeot  (and very unexpected) I/O error.  M_INTWAIT should be used for these cases.
1086eef04ebSFrançois Tigeot
1096eef04ebSFrançois Tigeot* CDEVSW conversion - see other devices.  Generally speaking a major number
1106eef04ebSFrançois Tigeot  is needed and a function map needs to be specified more explicitly.
1116eef04ebSFrançois Tigeot
1126eef04ebSFrançois Tigeot  Most calls passing struct cdev pointers are dev_t's in DragonFly.
1136eef04ebSFrançois Tigeot
1146eef04ebSFrançois Tigeot  All device vectors in DragonFly pass a dev_<name>_args structure pointer
1156eef04ebSFrançois Tigeot  instead of explicit arguments.
1166eef04ebSFrançois Tigeot
1176eef04ebSFrançois Tigeot  Strategy calls - we pass BIO's and a lot of BUF fields are in the BIO
1186eef04ebSFrançois Tigeot  in FreeBSD, but left in the BUF in DragonFly.  FreeBSD for some reason
1196eef04ebSFrançois Tigeot  names its struct bio pointers 'bp', its a good idea to rename them to 'bio'
1206eef04ebSFrançois Tigeot  to avoid confusion and have a struct buf *bp = bio->bio_buf; pointer to
1216eef04ebSFrançois Tigeot  access the buf.
1226eef04ebSFrançois Tigeot
1236eef04ebSFrançois Tigeot* MSLEEP/TSLEEP conversion.  The DragonFly msleep/tsleep do not have 'PRI'
1246eef04ebSFrançois Tigeot  priorities.  0 should be used.
1256eef04ebSFrançois Tigeot
1266eef04ebSFrançois Tigeot* BUS_* FUNCTIONS
1276eef04ebSFrançois Tigeot
1286eef04ebSFrançois Tigeot  bus_setup_intr() - replace INTR_TYPE_* flags with 0.  There is an extra
1296eef04ebSFrançois Tigeot  argument for an interrupt interlock using the sys/serializer.h interface.
1306eef04ebSFrançois Tigeot  This can either be left NULL or you can convert the spinlock(s) for
1316eef04ebSFrançois Tigeot  the driver into serializer locks and integrate the interrupt service
1326eef04ebSFrançois Tigeot  routine with a serializer.
1336eef04ebSFrançois Tigeot
1346eef04ebSFrançois Tigeot* CAM CODE - cam_simq* code refcounts, so shared device queues (raid and
1356eef04ebSFrançois Tigeot  multi-channel devices) are not freed before all references have gone
1366eef04ebSFrançois Tigeot  away.
137317f6748SFrançois Tigeot
138de612e47SFrançois Tigeot* UNRHDR functions - DragonFly uses a more generic idr(9) subsystem
139de612e47SFrançois Tigeot  compatible with the Linux API of the same name
140de612e47SFrançois Tigeot
141de612e47SFrançois Tigeot  This LWN article describes it in details: http://lwn.net/Articles/103209/
142de612e47SFrançois Tigeot
143de612e47SFrançois Tigeot  A typical conversion looks like this:
144de612e47SFrançois Tigeot
145de612e47SFrançois Tigeot  #include <sys/idr.h>
146de612e47SFrançois Tigeot
147de612e47SFrançois Tigeot  free_unr() has to be replaced by idr_remove()
148de612e47SFrançois Tigeot
149de612e47SFrançois Tigeot  alloc_unr() has to be replaced by a code sequence using idr_pre_get and
150de612e47SFrançois Tigeot  idr_get_new such as this one:
151de612e47SFrançois Tigeot
152de612e47SFrançois Tigeot  retry:
153de612e47SFrançois Tigeot	if (idr_pre_get(xxx) ==0) {
154de612e47SFrançois Tigeot	kprintf("Memory allocation error\n");
155de612e47SFrançois Tigeot	    return error;
156de612e47SFrançois Tigeot	}
157de612e47SFrançois Tigeot	spin_lock(xxx);
158de612e47SFrançois Tigeot	ret = idr_get_new(xxx);
159de612e47SFrançois Tigeot	spin_unlock(xxx);
160de612e47SFrançois Tigeot	if (ret == EAGAIN)
161de612e47SFrançois Tigeot	    goto retry;
162de612e47SFrançois Tigeot
1634dd401bdSFrançois Tigeot* MPASS macro - Replace it with KKASSERT
1642764c241SAntonio Huete Jimenez
165cf396422SFrançois Tigeot
166cf396422SFrançois Tigeot* PROC_LOCK / PROC_UNLOCK: to be determined on a case-by-case basis
167cf396422SFrançois Tigeot
168cf396422SFrançois Tigeot  Some of the time these macros can be removed entirely
169cf396422SFrançois Tigeot
170cf396422SFrançois Tigeot  In some cases, some locking must be done; lwkt_gettoken(&proc_token)
171cf396422SFrançois Tigeot  and the corresponding lwkt_reltoken() call should be good replacements
172cf396422SFrançois Tigeot
173cf396422SFrançois Tigeot  It is not a good idea to blindly implement these macros globally, some
174cf396422SFrançois Tigeot  particular proc subsystem locking semantics differ enough between FreeBSD
175cf396422SFrançois Tigeot  and DragonFly that this would cause problems
176cf396422SFrançois Tigeot
177d00c6212Szrj* In DragonFly 5.1 format specifier %b was replaced by args safe "%pb%i" version
178d00c6212Szrj  that only needs argument swapping. Replacement functions where not added.
179d00c6212Szrj
180d00c6212Szrj	kvcprintf("reg=%pb%i\n", "\10\2BITTWO\1BITONE\n", 3);
181d00c6212Szrj
182d00c6212Szrj* In DragonFly 5.1 format specifier %r was removed from kprintf. As a
183d00c6212Szrj  replacement function makedev_unit_b32() was added.
184d00c6212Szrj
185d00c6212Szrj  - Unit suffix encoded as base32 for make_dev() device creation:
186d00c6212Szrj
187d00c6212Szrj	char tbuf[MAKEDEV_MINNBUF];
188d00c6212Szrj
189d00c6212Szrj	kbd->kb_dev = make_dev(&kbd_ops, kbd->kb_index,
190d00c6212Szrj				UID_ROOT, GID_WHEEL, 0600, "kbd%s",
191d00c6212Szrj				makedev_unit_b32(tbuf, kbd->kb_index));
192d00c6212Szrj
193d00c6212Szrj  - For single character case the hex2ascii() can be used to avoid buffers:
194d00c6212Szrj
195d00c6212Szrj	kprintf("%c\n", hex2ascii(n % base));
196cf396422SFrançois Tigeot
1972764c241SAntonio Huete Jimenez* In DragonFly 3.3 format specifier %D was removed from kprintf. As a
1982764c241SAntonio Huete Jimenez  replacement functions kether_ntoa() and hexncpy() were added.
1992764c241SAntonio Huete Jimenez
2002764c241SAntonio Huete Jimenez  - Ethernet address (MAC) to its hexadecimal form:
2012764c241SAntonio Huete Jimenez
2022764c241SAntonio Huete Jimenez	char ethstr[ETHER_ADDRSTRLEN + 1];
2032764c241SAntonio Huete Jimenez	u_char hwaddr[6];
2042764c241SAntonio Huete Jimenez
2052764c241SAntonio Huete Jimenez	kprintf("MAC address %s\n", kether_ntoa(hwaddr, ethstr)
2062764c241SAntonio Huete Jimenez
2072764c241SAntonio Huete Jimenez  - Generic conversion (block of bytes to hexadecimal form):
2082764c241SAntonio Huete Jimenez
2092764c241SAntonio Huete Jimenez	char hexstr[18];
2102764c241SAntonio Huete Jimenez	u_char mydata[6] = {1, 2, 3, 4, 5 ,6};
2112764c241SAntonio Huete Jimenez
2122764c241SAntonio Huete Jimenez	/*
2132764c241SAntonio Huete Jimenez	 * Below statement would print:
2142764c241SAntonio Huete Jimenez	 *
2152764c241SAntonio Huete Jimenez	 * 01-02-03-04-05-06
2162764c241SAntonio Huete Jimenez	 */
2172764c241SAntonio Huete Jimenez	kprintf("%s\n", hexncpy(mydata, 6, hexstr, HEX_NCPYLEN(6), "-"));
2184b3fb495SFrançois Tigeot
2194b3fb495SFrançois Tigeot* TAILQ_XXX_SAFE
2204b3fb495SFrançois Tigeot
2214b3fb495SFrançois Tigeot  Use TAILQ_XXX_MUTABLE; the macros have the same effect, only the name is
2224b3fb495SFrançois Tigeot  different
2234b3fb495SFrançois Tigeot
2244b3fb495SFrançois Tigeot* kern_yield()
2254b3fb495SFrançois Tigeot
2264b3fb495SFrançois Tigeot  Replace by lwkt_yield()
2274b3fb495SFrançois Tigeot
2284b3fb495SFrançois Tigeot* vm_page_lock() and vm_page_unlock()
2294b3fb495SFrançois Tigeot
2304b3fb495SFrançois Tigeot  Not needed on DragonFly, remove these calls
2314b3fb495SFrançois Tigeot
2324b3fb495SFrançois Tigeot* vm_pager_get_pages()
2334b3fb495SFrançois Tigeot
2344b3fb495SFrançois Tigeot  Removed, use vm_pager_get_page() instead
2354b3fb495SFrançois Tigeot
2364b3fb495SFrançois Tigeot* VPO_BUSY
2374b3fb495SFrançois Tigeot
2384b3fb495SFrançois Tigeot  Replace by PG_BUSY
2394b3fb495SFrançois Tigeot
2404b3fb495SFrançois Tigeot* kern_psignal()
2414b3fb495SFrançois Tigeot
2424b3fb495SFrançois Tigeot  Replace by ksignal()
243